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