1 /*
2  * Author: Harry van Haaren 2013
3  *         harryhaaren@gmail.com
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18  * MA 02110-1301, USA.
19  */
20 
21 #include "della.hxx"
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <math.h>
27 
28 #include "dsp_delay.hxx"
29 
30 #include "lv2/lv2plug.in/ns/ext/atom/atom.h"
31 #include "lv2/lv2plug.in/ns/ext/atom/util.h"
32 #include "lv2/lv2plug.in/ns/ext/urid/urid.h"
33 #include "lv2/lv2plug.in/ns/ext/time/time.h"
34 
35 
36 
instantiate(const LV2_Descriptor * descriptor,double samplerate,const char * bundle_path,const LV2_Feature * const * features)37 LV2_Handle Della::instantiate(const LV2_Descriptor* descriptor,
38                               double samplerate,
39                               const char* bundle_path,
40                               const LV2_Feature* const* features)
41 {
42 	Della* d = new Della( samplerate );
43 	d->map = 0;
44 
45 	// get URID_map and unmap
46 	for (int i = 0; features[i]; i++) {
47 		if (!strcmp(features[i]->URI, LV2_URID__map)) {
48 			d->map = (LV2_URID_Map*)features[i]->data;
49 		}
50 	}
51 
52 	// we don't have the map extension: print warning
53 	if( !d->map ) {
54 		printf("Della: Error: host doesn't provide Lv2 URID map, cannot sync BPM!\n");
55 		delete d;
56 		return 0;
57 	}
58 
59 	// Get URID's for Lv2 TIME / ATOM extensions
60 	d->time_Position      = d->map->map(d->map->handle, LV2_TIME__Position);
61 	d->time_barBeat       = d->map->map(d->map->handle, LV2_TIME__barBeat);
62 	d->time_beatsPerMinute= d->map->map(d->map->handle, LV2_TIME__beatsPerMinute);
63 	d->time_speed         = d->map->map(d->map->handle, LV2_TIME__speed);
64 
65 	d->atom_Blank         = d->map->map(d->map->handle, LV2_ATOM__Blank);
66 	d->atom_Float         = d->map->map(d->map->handle, LV2_ATOM__Float);
67 
68 	return (LV2_Handle) d;
69 }
70 
Della(int rate)71 Della::Della(int rate)
72 {
73 	delay = new Delay( rate );
74 }
75 
activate(LV2_Handle instance)76 void Della::activate(LV2_Handle instance)
77 {
78 }
79 
deactivate(LV2_Handle instance)80 void Della::deactivate(LV2_Handle instance)
81 {
82 }
83 
connect_port(LV2_Handle instance,uint32_t port,void * data)84 void Della::connect_port(LV2_Handle instance, uint32_t port, void *data)
85 {
86 	Della* self = (Della*) instance;
87 
88 	switch (port) {
89 	case DELLA_INPUT:
90 		self->audioInput    = (float*)data;
91 		break;
92 	case DELLA_OUTPUT:
93 		self->audioOutput   = (float*)data;
94 		break;
95 
96 	case DELLA_TIME:
97 		self->controlDelay  = (float*)data;
98 		break;
99 	case DELLA_VOLUME:
100 		self->controlVolume = (float*)data;
101 		break;
102 	case DELLA_FEEDBACK:
103 		self->controlFeedback = (float*)data;
104 		break;
105 	case DELLA_ACTIVE:
106 		self->controlActive = (float*)data;
107 		break;
108 
109 	case DELLA_ATOM_IN:
110 		self->atom_port      = (LV2_Atom_Sequence*)data;
111 		break;
112 	}
113 }
114 
run(LV2_Handle instance,uint32_t n_samples)115 void Della::run(LV2_Handle instance, uint32_t n_samples)
116 {
117 	Della* self = (Della*) instance;
118 
119 	/// audio inputs
120 	float* in  = self->audioInput;
121 	float* out = self->audioOutput;
122 
123 	/// control inputs
124 	float active    = *self->controlActive;
125 	float delay     = *self->controlDelay;
126 	float volume    = *self->controlVolume;
127 	float feedback  = *self->controlFeedback;
128 
129 	/// handle Atom messages
130 	LV2_ATOM_SEQUENCE_FOREACH(self->atom_port, ev) {
131 		if ( ev->body.type == self->atom_Blank ) {
132 			const LV2_Atom_Object* obj = (LV2_Atom_Object*)&ev->body;
133 			//printf("time_Position message\n" );
134 			LV2_Atom* bpm = 0;
135 			lv2_atom_object_get(obj,
136 			                    self->time_beatsPerMinute, &bpm,
137 			                    NULL);
138 
139 			if ( bpm ) { //&& bpm->type == self->atom_Float) {
140 				// Tempo changed, update BPM
141 				float bpmValue = ((LV2_Atom_Float*)bpm)->body;
142 				//self->dspMasherL->bpm( bpmValue );
143 				//printf("set bpm of %f\n", bpmValue );
144 				self->delay->setBPM( bpmValue );
145 			}
146 
147 		} else {
148 			//printf("atom message: %s\n", self->unmap->unmap( self->unmap->handle, ev->body.type ) );
149 		}
150 	}
151 
152 	if ( active > 0.5 )
153 		self->delay->active( true  );
154 	else
155 		self->delay->active( false );
156 
157 	self->delay->setValue( delay );
158 	self->delay->setVolume( volume );
159 	self->delay->setFeedback( feedback );
160 
161 	self->delay->process( n_samples, in, out );
162 }
163 
cleanup(LV2_Handle instance)164 void Della::cleanup(LV2_Handle instance)
165 {
166 	delete ((Della*)instance)->delay;
167 
168 	delete ((Della*) instance);
169 }
170 
extension_data(const char * uri)171 const void* Della::extension_data(const char* uri)
172 {
173 	return NULL;
174 }
175