/* * CINELERRA * Copyright (C) 2008 Adam Williams * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "bcdisplayinfo.h" #include "clip.h" #include "bchash.h" #include "guicast.h" #include "filexml.h" #include "language.h" #include "mainprogress.h" #include "pluginaclient.h" #include "samples.h" #include "transportque.h" #include class InterpolateAudioEffect : public PluginAClient { public: InterpolateAudioEffect(PluginServer *server); ~InterpolateAudioEffect(); const char* plugin_title(); int process_buffer(int64_t size, Samples *buffer, int64_t start_position, int sample_rate); int is_realtime(); #define FRAGMENT_SIZE 4096 Samples *start_fragment; Samples *end_fragment; double start_sample; double end_sample; int64_t range_start; int64_t range_end; }; REGISTER_PLUGIN(InterpolateAudioEffect) InterpolateAudioEffect::InterpolateAudioEffect(PluginServer *server) : PluginAClient(server) { start_fragment = 0; end_fragment = 0; } InterpolateAudioEffect::~InterpolateAudioEffect() { if(start_fragment) delete start_fragment; if(end_fragment) delete end_fragment; } const char* InterpolateAudioEffect::plugin_title() { return N_("Interpolate"); } int InterpolateAudioEffect::is_realtime() { return 1; } int InterpolateAudioEffect::process_buffer(int64_t size, Samples *buffer, int64_t start_position, int sample_rate) { if(!start_fragment) start_fragment = new Samples(FRAGMENT_SIZE); if(!end_fragment) end_fragment = new Samples(FRAGMENT_SIZE); double *buffer_samples = buffer->get_data(); double *start_samples = start_fragment->get_data(); double *end_samples = end_fragment->get_data(); if(get_direction() == PLAY_FORWARD) { // On first sample of range. Get boundary samples of effect. if(get_source_position() == get_source_start()) { // Need to read before desired sample to diffuse transients after audio // seeks. range_start = get_source_start(); range_end = get_source_start() + get_total_len(); //printf("InterpolateAudioEffect::process_buffer 1 %p\n", start_fragment); read_samples(start_fragment, 0, sample_rate, range_start - FRAGMENT_SIZE, FRAGMENT_SIZE); start_sample = start_samples[FRAGMENT_SIZE - 1]; read_samples(end_fragment, 0, sample_rate, range_end - FRAGMENT_SIZE, FRAGMENT_SIZE); end_sample = end_samples[FRAGMENT_SIZE - 1]; } for(int i = 0; i < size; i++) { double end_fraction = (double)(i + start_position - range_start) / (range_end - range_start); double start_fraction = 1.0 - end_fraction; double out_sample = start_sample * start_fraction + end_sample * end_fraction; buffer_samples[i] = out_sample; } } else { // On first sample of range. Get boundary samples of effect. if(get_source_position() == get_source_start() + get_total_len()) { // Need to read before desired sample to diffuse transients after audio // seeks. range_start = get_source_start() + get_total_len(); range_end = get_source_start(); read_samples(start_fragment, 0, sample_rate, range_start, FRAGMENT_SIZE); start_sample = start_samples[0]; read_samples(end_fragment, 0, sample_rate, range_end, FRAGMENT_SIZE); end_sample = end_samples[0]; } for(int i = 0; i < size; i++) { double start_fraction = (double)(start_position - i - range_end) / (range_start - range_end); double end_fraction = 1.0 - start_fraction; double out_sample = start_sample * start_fraction + end_sample * end_fraction; buffer_samples[i] = out_sample; } } return 0; }