1 /***************************************************************************
2  *   Copyright (C) 2011 by Pere Ràfols Soler                               *
3  *   sapista2@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                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20 
21 /***************************************************************************
22 This file is the implementation of the BassUp plugin
23 This plugin is inside the Sapista Plugins Bundle
24 ****************************************************************************/
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <math.h>
29 
30 #include <lv2/lv2plug.in/ns/lv2core/lv2.h>
31 #include "dsp/filter.h"
32 
33 #define BASSUP_URI "http://eq10q.sourceforge.net/bassup"
34 #define PORT_OUTPUT 0
35 #define PORT_INPUT 1
36 #define PORT_AMOUNT 2
37 
38 #define NUM_OF_HPF_STAGES 4
39 #define HPF_FREQ 50.0f
40 #define LPF_FREQ 200.0f
41 
42 typedef struct {
43   //Plugin ports
44   float *amount;
45   float *output;
46   const float *input;
47 
48   //Plugin Internal data
49   float sample_rate;
50   Filter *LPF_fil, *HPF_fil[4];
51   Buffers LPF_buf, HPF_buf[4];
52 } BassUp;
53 
cleanupBassUp(LV2_Handle instance)54 static void cleanupBassUp(LV2_Handle instance)
55 {
56   BassUp *plugin = (BassUp *)instance;
57   int i;
58   for(i=0; i<NUM_OF_HPF_STAGES; i++)
59   {
60       FilterClean(plugin->HPF_fil[i]);
61   }
62   FilterClean(plugin->LPF_fil);
63   free(instance);
64 }
65 
connectPortBassUp(LV2_Handle instance,uint32_t port,void * data)66 static void connectPortBassUp(LV2_Handle instance, uint32_t port, void *data)
67 {
68   BassUp *plugin = (BassUp *)instance;
69   switch (port) {
70     case PORT_AMOUNT:
71             plugin->amount = (float*)data;
72             break;
73       case PORT_INPUT:
74             plugin->input = (const float*)data;
75             break;
76     case PORT_OUTPUT:
77             plugin->output = (float*)data;
78             break;
79   }
80 }
81 
instantiateBassUp(const LV2_Descriptor * descriptor,double s_rate,const char * path,const LV2_Feature * const * features)82 static LV2_Handle instantiateBassUp(const LV2_Descriptor *descriptor, double s_rate, const char *path, const LV2_Feature *const * features)
83 {
84   BassUp *plugin_data = (BassUp *)malloc(sizeof(BassUp));
85   plugin_data->sample_rate = s_rate;
86   int i;
87   for(i =0; i<NUM_OF_HPF_STAGES; i++)
88   {
89     plugin_data->HPF_fil[i] = FilterInit(s_rate);
90     flushBuffers(&plugin_data->HPF_buf[i]);
91     calcCoefs(plugin_data->HPF_fil[i], 0.0, HPF_FREQ, 0.75, F_HPF_ORDER_2, 1.0);
92   }
93   plugin_data->LPF_fil = FilterInit(s_rate);
94   flushBuffers(&plugin_data->LPF_buf);
95   calcCoefs(plugin_data->LPF_fil, 0.0, LPF_FREQ, 0.75, F_LPF_ORDER_2, 1.0);
96   return (LV2_Handle)plugin_data;
97 }
98 
99 #define DENORMAL_TO_ZERO_FLOAT(x) if (fabs(x) < (1e-30)) x = 0.f; //Min float is 1.1754943e-38
runBassUp(LV2_Handle instance,uint32_t sample_count)100 static void runBassUp(LV2_Handle instance, uint32_t sample_count)
101 {
102   BassUp *plugin_data = (BassUp *)instance;
103   const float amount = *(plugin_data->amount);
104   double bassSignal;
105 
106   for (uint32_t i = 0; i < sample_count; ++i)
107   {
108     //bassSignal
109     bassSignal = (double)fabs(plugin_data->input[i]);
110 
111     //Apply Filters
112     int j;
113     for(j=0; j<NUM_OF_HPF_STAGES; j++)
114     {
115       computeFilter(plugin_data->HPF_fil[j], &plugin_data->HPF_buf[j], &bassSignal);
116     }
117     computeFilter(plugin_data->LPF_fil, &plugin_data->LPF_buf, &bassSignal);
118 
119     //Output
120     plugin_data->output[i] = (float)bassSignal*amount + plugin_data->input[i];
121   }
122 }
123 
124 static const LV2_Descriptor bassupDescriptor = {
125   BASSUP_URI,
126   instantiateBassUp,
127   connectPortBassUp,
128   NULL,
129   runBassUp,
130   NULL,
131   cleanupBassUp,
132   NULL
133 };
134 
135 LV2_SYMBOL_EXPORT
lv2_descriptor(uint32_t index)136 const LV2_Descriptor *lv2_descriptor(uint32_t index)
137 {
138   switch (index) {
139   case 0:
140     return &bassupDescriptor;
141   default:
142     return NULL;
143   }
144 }
145