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 "bitta.hxx"
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <math.h>
27 
28 #include "dsp_bitcrusher.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 
instantiate(const LV2_Descriptor * descriptor,double samplerate,const char * bundle_path,const LV2_Feature * const * features)35 LV2_Handle Bitta::instantiate(const LV2_Descriptor* descriptor,
36                               double samplerate,
37                               const char* bundle_path,
38                               const LV2_Feature* const* features)
39 {
40 	Bitta* d = new Bitta( samplerate );
41 	d->map = 0;
42 
43 	// get URID_map and unmap
44 	for (int i = 0; features[i]; i++) {
45 		if (!strcmp(features[i]->URI, LV2_URID__map)) {
46 			d->map = (LV2_URID_Map*)features[i]->data;
47 		}
48 	}
49 
50 	// we don't have the map extension: print warning
51 	if( !d->map ) {
52 		printf("Bitta: Error: host doesn't provide Lv2 URID map, cannot sync BPM!\n");
53 		delete d;
54 		return 0;
55 	}
56 
57 	// Get URID's for Lv2 TIME / ATOM extensions
58 	d->time_Position      = d->map->map(d->map->handle, LV2_TIME__Position);
59 	d->time_barBeat       = d->map->map(d->map->handle, LV2_TIME__barBeat);
60 	d->time_beatsPerMinute= d->map->map(d->map->handle, LV2_TIME__beatsPerMinute);
61 	d->time_speed         = d->map->map(d->map->handle, LV2_TIME__speed);
62 
63 	d->atom_Blank         = d->map->map(d->map->handle, LV2_ATOM__Blank);
64 	d->atom_Float         = d->map->map(d->map->handle, LV2_ATOM__Float);
65 
66 	return (LV2_Handle) d;
67 }
68 
Bitta(int rate)69 Bitta::Bitta(int rate)
70 {
71 	bitcrusher = new BitCrusher( rate );
72 }
73 
activate(LV2_Handle instance)74 void Bitta::activate(LV2_Handle instance)
75 {
76 }
77 
deactivate(LV2_Handle instance)78 void Bitta::deactivate(LV2_Handle instance)
79 {
80 }
81 
connect_port(LV2_Handle instance,uint32_t port,void * data)82 void Bitta::connect_port(LV2_Handle instance, uint32_t port, void *data)
83 {
84 	Bitta* self = (Bitta*) instance;
85 
86 	switch (port) {
87 	case BITTA_INPUT_L:
88 		self->audioInputL  = (float*)data;
89 		break;
90 	case BITTA_OUTPUT_L:
91 		self->audioOutputL = (float*)data;
92 		break;
93 
94 	case BITTA_CRUSH:
95 		self->controlCrush  = (float*)data;
96 		break;
97 	case BITTA_DRYWET:
98 		self->controlDryWet  = (float*)data;
99 		break;
100 	case BITTA_ACTIVE:
101 		self->controlActive = (float*)data;
102 		break;
103 
104 	case BITTA_ATOM_IN:
105 		self->atom_port      = (LV2_Atom_Sequence*)data;
106 		break;
107 	}
108 }
109 
run(LV2_Handle instance,uint32_t n_samples)110 void Bitta::run(LV2_Handle instance, uint32_t n_samples)
111 {
112 	Bitta* self = (Bitta*) instance;
113 
114 	/// audio inputs
115 	float* inL  = self->audioInputL;
116 	float* outL = self->audioOutputL;
117 
118 	/// control inputs
119 	float active    = *self->controlActive;
120 	float width     = *self->controlCrush;
121 	float dryWet    = *self->controlDryWet;
122 
123 	/// handle Atom messages
124 	LV2_ATOM_SEQUENCE_FOREACH(self->atom_port, ev) {
125 		if ( ev->body.type == self->atom_Blank ) {
126 			const LV2_Atom_Object* obj = (LV2_Atom_Object*)&ev->body;
127 			//printf("time_Position message\n" );
128 			LV2_Atom* bpm = 0;
129 			lv2_atom_object_get(obj,
130 			                    self->time_beatsPerMinute, &bpm,
131 			                    NULL);
132 
133 			if ( bpm ) { //&& bpm->type == self->atom_Float) {
134 				// Tempo changed, update BPM
135 				float bpmValue = ((LV2_Atom_Float*)bpm)->body;
136 				//self->dspMasherL->bpm( bpmValue );
137 				//printf("set bpm of %f\n", bpmValue );
138 				//self->bitcrusher->setBPM( bpmValue );
139 			}
140 
141 		} else {
142 			//printf("atom message: %s\n", self->unmap->unmap( self->unmap->handle, ev->body.type ) );
143 		}
144 	}
145 
146 	if ( active > 0.5 )
147 		self->bitcrusher->active( true  );
148 	else
149 		self->bitcrusher->active( false );
150 
151 	self->bitcrusher->setValue( width );
152 
153 	self->bitcrusher->setDryWet( dryWet );
154 
155 	self->bitcrusher->process( n_samples, inL, outL );
156 }
157 
cleanup(LV2_Handle instance)158 void Bitta::cleanup(LV2_Handle instance)
159 {
160 	delete ((Bitta*)instance)->bitcrusher;
161 
162 	delete ((Bitta*) instance);
163 }
164 
extension_data(const char * uri)165 const void* Bitta::extension_data(const char* uri)
166 {
167 	return NULL;
168 }
169