1 #include "bcdisplayinfo.h"
16 #define WINDOW_SIZE 4096
20 REGISTER_PLUGIN(PitchEffect);
26 PitchEffect::PitchEffect(PluginServer *server)
27 : PluginAClient(server)
29 PLUGIN_CONSTRUCTOR_MACRO
33 PitchEffect::~PitchEffect()
35 PLUGIN_DESTRUCTOR_MACRO
40 char* PitchEffect::plugin_title() { return N_("Pitch shift"); }
41 int PitchEffect::is_realtime() { return 1; }
45 void PitchEffect::read_data(KeyFrame *keyframe)
48 input.set_shared_string(keyframe->data, strlen(keyframe->data));
53 result = input.read_tag();
57 if(input.tag.title_is("PITCH"))
59 config.scale = input.tag.get_property("SCALE", config.scale);
65 void PitchEffect::save_data(KeyFrame *keyframe)
68 output.set_shared_string(keyframe->data, MESSAGESIZE);
70 output.tag.set_title("PITCH");
71 output.tag.set_property("SCALE", config.scale);
73 output.append_newline();
75 output.terminate_string();
78 int PitchEffect::load_defaults()
80 char directory[BCTEXTLEN], string[BCTEXTLEN];
81 sprintf(directory, "%spitch.rc", BCASTDIR);
82 defaults = new Defaults(directory);
85 config.scale = defaults->get("SCALE", config.scale);
89 int PitchEffect::save_defaults()
91 char string[BCTEXTLEN];
93 defaults->update("SCALE", config.scale);
100 LOAD_CONFIGURATION_MACRO(PitchEffect, PitchConfig)
102 SHOW_GUI_MACRO(PitchEffect, PitchThread)
104 RAISE_WINDOW_MACRO(PitchEffect)
106 SET_STRING_MACRO(PitchEffect)
108 NEW_PICON_MACRO(PitchEffect)
111 void PitchEffect::reset()
116 void PitchEffect::update_gui()
120 load_configuration();
121 thread->window->lock_window("PitchEffect::update_gui");
122 thread->window->update();
123 thread->window->unlock_window();
127 int PitchEffect::process_buffer(int64_t size,
129 int64_t start_position,
132 load_configuration();
135 fft = new PitchFFT(this);
136 fft->initialize(WINDOW_SIZE);
138 fft->process_buffer(start_position,
153 PitchFFT::PitchFFT(PitchEffect *plugin)
156 this->plugin = plugin;
160 int PitchFFT::signal_process()
163 1 + (int)(20.0 / ((double)plugin->PluginAClient::project_sample_rate /
164 window_size * 2) + 0.5);
165 if(plugin->config.scale < 1)
167 for(int i = min_freq; i < window_size / 2; i++)
169 double destination = i * plugin->config.scale;
170 int dest_i = (int)(destination + 0.5);
173 if(dest_i <= window_size / 2)
175 freq_real[dest_i] = freq_real[i];
176 freq_imag[dest_i] = freq_imag[i];
184 if(plugin->config.scale > 1)
186 for(int i = window_size / 2 - 1; i >= min_freq; i--)
188 double destination = i * plugin->config.scale;
189 int dest_i = (int)(destination + 0.5);
192 if(dest_i <= window_size / 2)
194 freq_real[dest_i] = freq_real[i];
195 freq_imag[dest_i] = freq_imag[i];
203 symmetry(window_size, freq_real, freq_imag);
208 int PitchFFT::read_samples(int64_t output_sample,
212 return plugin->read_samples(buffer,
214 plugin->get_samplerate(),
225 PitchConfig::PitchConfig()
230 int PitchConfig::equivalent(PitchConfig &that)
232 return EQUIV(scale, that.scale);
235 void PitchConfig::copy_from(PitchConfig &that)
240 void PitchConfig::interpolate(PitchConfig &prev,
244 int64_t current_frame)
246 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
247 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
248 scale = prev.scale * prev_scale + next.scale * next_scale;
258 PLUGIN_THREAD_OBJECT(PitchEffect, PitchThread, PitchWindow)
268 PitchWindow::PitchWindow(PitchEffect *plugin, int x, int y)
269 : BC_Window(plugin->gui_string,
280 this->plugin = plugin;
283 void PitchWindow::create_objects()
287 add_subwindow(new BC_Title(x, y, _("Scale:")));
289 add_subwindow(scale = new PitchScale(plugin, x, y));
294 WINDOW_CLOSE_EVENT(PitchWindow)
296 void PitchWindow::update()
298 scale->update(plugin->config.scale);
312 PitchScale::PitchScale(PitchEffect *plugin, int x, int y)
313 : BC_FPot(x, y, (float)plugin->config.scale, .5, 1.5)
315 this->plugin = plugin;
319 int PitchScale::handle_event()
321 plugin->config.scale = get_value();
322 plugin->send_configure_change();