int OverlayAudio::process_buffer(int64_t size, Samples **buffer, int64_t start_position, int sample_rate) { load_configuration(); int output_track = 0; if(config.output_track == OverlayAudioConfig::BOTTOM) output_track = get_total_buffers() - 1; // Direct copy the output track read_samples(buffer[output_track], output_track, sample_rate, start_position, size); // Add remaining tracks Samples *output_buffer = buffer[output_track]; double *output_samples = output_buffer->get_data(); for(int i = 0; i < get_total_buffers(); i++) { if(i != output_track) { Samples *input_buffer = buffer[i]; read_samples(buffer[i], i, sample_rate, start_position, size); double *input_samples = input_buffer->get_data(); switch(config.mode) { case OverlayAudioConfig::ADD: for(int j = 0; j < size; j++) { output_samples[j] += input_samples[j]; } break; case OverlayAudioConfig::MULTIPLY: for(int j = 0; j < size; j++) { output_samples[j] *= input_samples[j]; } break; } } } return 0; }
int TimeFrontMain::process_buffer(VFrame **frame, int64_t start_position, double frame_rate) //int TimeFrontMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr) { VFrame **outframes = frame; VFrame *(framelist[1024]); framelist[0] = new VFrame ( outframes[0]->get_w(), outframes[0]->get_h(), outframes[0]->get_color_model()); read_frame(framelist[0], 0, start_position, frame_rate); this->input = framelist[0]; this->output = outframes[0]; need_reconfigure |= load_configuration(); if (config.shape == TimeFrontConfig::OTHERTRACK) { // this->output = frame[1]; if (get_total_buffers() != 2) { // FIXME, maybe this should go to some other notification area? printf("ERROR: TimeFront plugin - If you are using another track for timefront, you have to have it under shared effects\n"); return 0; } if (outframes[0]->get_w() != outframes[1]->get_w() || outframes[0]->get_h() != outframes[1]->get_h()) { printf("Sizes of master track and timefront track do not match\n"); return 0; } } // Generate new gradient if(need_reconfigure) { need_reconfigure = 0; if(!gradient) gradient = new VFrame( outframes[0]->get_w(), outframes[0]->get_h(), BC_A8); if (config.shape != TimeFrontConfig::OTHERTRACK && config.shape != TimeFrontConfig::ALPHA) { if(!engine) engine = new TimeFrontServer(this, get_project_smp() + 1, get_project_smp() + 1); engine->process_packages(); } } if (config.shape == TimeFrontConfig::ALPHA) { if(!gradient) gradient = new VFrame( outframes[0]->get_w(), outframes[0]->get_h(), BC_A8); VFrame *tfframe = framelist[0]; switch (tfframe->get_color_model()) { case BC_YUVA8888: case BC_RGBA8888: GRADIENTFROMCHANNEL(unsigned char, 4, 255, 3); break; case BC_RGBA_FLOAT: GRADIENTFROMCHANNEL(float, 4, 1.0f, 3); break; default: { printf("TimeFront plugin error: ALPHA used, but project color model does not have alpha\n"); return 1; break; } } } else if (config.shape == TimeFrontConfig::OTHERTRACK)
int CompressorEffect::process_buffer(int64_t size, Samples **buffer, int64_t start_position, int sample_rate) { load_configuration(); // Calculate linear transfer from db levels.remove_all(); for(int i = 0; i < config.levels.total; i++) { levels.append(); levels.values[i].x = DB::fromdb(config.levels.values[i].x); levels.values[i].y = DB::fromdb(config.levels.values[i].y); } min_x = DB::fromdb(config.min_db); min_y = DB::fromdb(config.min_db); max_x = 1.0; max_y = 1.0; int reaction_samples = (int)(config.reaction_len * sample_rate + 0.5); int decay_samples = (int)(config.decay_len * sample_rate + 0.5); int trigger = CLIP(config.trigger, 0, PluginAClient::total_in_buffers - 1); CLAMP(reaction_samples, -1000000, 1000000); CLAMP(decay_samples, reaction_samples, 1000000); CLAMP(decay_samples, 1, 1000000); if(labs(reaction_samples) < 1) reaction_samples = 1; if(labs(decay_samples) < 1) decay_samples = 1; int total_buffers = get_total_buffers(); if(reaction_samples >= 0) { if(target_current_sample < 0) target_current_sample = reaction_samples; for(int i = 0; i < total_buffers; i++) { read_samples(buffer[i], i, sample_rate, start_position, size); } double current_slope = (next_target - previous_target) / reaction_samples; double *trigger_buffer = buffer[trigger]->get_data(); for(int i = 0; i < size; i++) { // Get slope required to reach current sample from smoothed sample over reaction // length. double sample; switch(config.input) { case CompressorConfig::MAX: { double max = 0; for(int j = 0; j < total_buffers; j++) { sample = fabs(buffer[j]->get_data()[i]); if(sample > max) max = sample; } sample = max; break; } case CompressorConfig::TRIGGER: sample = fabs(trigger_buffer[i]); break; case CompressorConfig::SUM: { double max = 0; for(int j = 0; j < total_buffers; j++) { sample = fabs(buffer[j]->get_data()[i]); max += sample; } sample = max; break; } } double new_slope = (sample - current_value) / reaction_samples; // Slope greater than current slope if(new_slope >= current_slope && (current_slope >= 0 || new_slope >= 0)) { next_target = sample; previous_target = current_value; target_current_sample = 0; target_samples = reaction_samples; current_slope = new_slope; } else if(sample > next_target && current_slope < 0) { next_target = sample; previous_target = current_value; target_current_sample = 0; target_samples = decay_samples; current_slope = (sample - current_value) / decay_samples; } // Current smoothed sample came up without finding higher slope if(target_current_sample >= target_samples) { next_target = sample; previous_target = current_value; target_current_sample = 0; target_samples = decay_samples; current_slope = (sample - current_value) / decay_samples; } // Update current value and store gain current_value = (next_target * target_current_sample + previous_target * (target_samples - target_current_sample)) / target_samples; target_current_sample++; if(config.smoothing_only) { for(int j = 0; j < total_buffers; j++) buffer[j]->get_data()[i] = current_value; } else { double gain = calculate_gain(current_value); for(int j = 0; j < total_buffers; j++) { buffer[j]->get_data()[i] *= gain; } } } } else { if(target_current_sample < 0) target_current_sample = target_samples; int64_t preview_samples = -reaction_samples; // Start of new buffer is outside the current buffer. Start buffer over. if(start_position < input_start || start_position >= input_start + input_size) { input_size = 0; input_start = start_position; } else // Shift current buffer so the buffer starts on start_position if(start_position > input_start && start_position < input_start + input_size) { if(input_buffer) { int len = input_start + input_size - start_position; for(int i = 0; i < total_buffers; i++) { memcpy(input_buffer[i]->get_data(), input_buffer[i]->get_data() + (start_position - input_start), len * sizeof(double)); } input_size = len; input_start = start_position; } } // Expand buffer to handle preview size if(size + preview_samples > input_allocated) { Samples **new_input_buffer = new Samples*[total_buffers]; for(int i = 0; i < total_buffers; i++) { new_input_buffer[i] = new Samples(size + preview_samples); if(input_buffer) { memcpy(new_input_buffer[i]->get_data(), input_buffer[i]->get_data(), input_size * sizeof(double)); delete input_buffer[i]; } } if(input_buffer) delete [] input_buffer; input_allocated = size + preview_samples; input_buffer = new_input_buffer; } // Append data to input buffer to construct readahead area. #define MAX_FRAGMENT_SIZE 131072 while(input_size < size + preview_samples) { int fragment_size = MAX_FRAGMENT_SIZE; if(fragment_size + input_size > size + preview_samples) fragment_size = size + preview_samples - input_size; for(int i = 0; i < total_buffers; i++) { input_buffer[i]->set_offset(input_size); //printf("CompressorEffect::process_buffer %d %p %d\n", __LINE__, input_buffer[i], input_size); read_samples(input_buffer[i], i, sample_rate, input_start + input_size, fragment_size); input_buffer[i]->set_offset(0); } input_size += fragment_size; } double current_slope = (next_target - previous_target) / target_samples; double *trigger_buffer = input_buffer[trigger]->get_data(); for(int i = 0; i < size; i++) { // Get slope from current sample to every sample in preview_samples. // Take highest one or first one after target_samples are up. // For optimization, calculate the first slope we really need. // Assume every slope up to the end of preview_samples has been calculated and // found <= to current slope. int first_slope = preview_samples - 1; // Need new slope immediately if(target_current_sample >= target_samples) first_slope = 1; for(int j = first_slope; j < preview_samples; j++) { double sample; switch(config.input) { case CompressorConfig::MAX: { double max = 0; for(int k = 0; k < total_buffers; k++) { sample = fabs(input_buffer[k]->get_data()[i + j]); if(sample > max) max = sample; } sample = max; break; } case CompressorConfig::TRIGGER: sample = fabs(trigger_buffer[i + j]); break; case CompressorConfig::SUM: { double max = 0; for(int k = 0; k < total_buffers; k++) { sample = fabs(input_buffer[k]->get_data()[i + j]); max += sample; } sample = max; break; } } double new_slope = (sample - current_value) / j; // Got equal or higher slope if(new_slope >= current_slope && (current_slope >= 0 || new_slope >= 0)) { target_current_sample = 0; target_samples = j; current_slope = new_slope; next_target = sample; previous_target = current_value; } else if(sample > next_target && current_slope < 0) { target_current_sample = 0; target_samples = decay_samples; current_slope = (sample - current_value) / decay_samples; next_target = sample; previous_target = current_value; } // Hit end of current slope range without finding higher slope if(target_current_sample >= target_samples) { target_current_sample = 0; target_samples = decay_samples; current_slope = (sample - current_value) / decay_samples; next_target = sample; previous_target = current_value; } } // Update current value and multiply gain current_value = (next_target * target_current_sample + previous_target * (target_samples - target_current_sample)) / target_samples; //buffer[0][i] = current_value; target_current_sample++; if(config.smoothing_only) { for(int j = 0; j < total_buffers; j++) { buffer[j]->get_data()[i] = current_value; } } else { double gain = calculate_gain(current_value); for(int j = 0; j < total_buffers; j++) { buffer[j]->get_data()[i] = input_buffer[j]->get_data()[i] * gain; } } } } return 0; }
int Vocoder::process_buffer(int64_t size, Samples **buffer, int64_t start_position, int sample_rate) { need_reconfigure |= load_configuration(); if(need_reconfigure) reconfigure(); // Process all except output channel int carrier_track = config.carrier_track; CLAMP(carrier_track, 0, PluginClient::get_total_buffers() - 1); int formant_track = 0; if(carrier_track == 0) formant_track = 1; CLAMP(formant_track, 0, PluginClient::get_total_buffers() - 1); // Copy level controls to band levels for(int i = 0; i < current_bands; i++) { output_bands[i].level = 1.0; } for(int i = 0; i < get_total_buffers(); i++) { read_samples(buffer[i], i, get_samplerate(), start_position, size); } double *carrier_samples = buffer[carrier_track]->get_data(); double *formant_samples = buffer[formant_track]->get_data(); double *output = buffer[0]->get_data(); double wetness = DB::fromdb(config.wetness); double level = DB::fromdb(config.level); for(int i = 0; i < size; i++) { do_bandpasses(carrier_bands, carrier_samples[i]); do_bandpasses(formant_bands, formant_samples[i]); output[i] *= wetness; double accum = 0; for(int j = 0; j < current_bands; j++) { output_bands[j].oldval = output_bands[j].oldval + (fabs (formant_bands[j].y) - output_bands[j].oldval) * output_bands[j].decay; double x = carrier_bands[j].y * output_bands[j].oldval; accum += x * output_bands[j].level; } accum *= level; output[i] += accum; } return 0; }
int Overlay::process_buffer(VFrame **frame, int64_t start_position, double frame_rate) { load_configuration(); printf("Overlay::process_buffer mode=%d\n", config.mode); if(!temp) temp = new VFrame(0, -1, frame[0]->get_w(), frame[0]->get_h(), frame[0]->get_color_model(), -1); if(!overlayer) overlayer = new OverlayFrame(get_project_smp() + 1); int step; VFrame *output; if(config.direction == OverlayConfig::BOTTOM_FIRST) { input_layer1 = get_total_buffers() - 1; input_layer2 = -1; step = -1; } else { input_layer1 = 0; input_layer2 = get_total_buffers(); step = 1; } if(config.output_layer == OverlayConfig::TOP) { output_layer = 0; } else { output_layer = get_total_buffers() - 1; } // Direct copy the first layer output = frame[output_layer]; read_frame(output, input_layer1, start_position, frame_rate, get_use_opengl()); if(get_total_buffers() == 1) return 0; current_layer = input_layer1; if(get_use_opengl()) run_opengl(); for(int i = input_layer1 + step; i != input_layer2; i += step) { read_frame(temp, i, start_position, frame_rate, get_use_opengl()); // Call the opengl handler once for each layer if(get_use_opengl()) { current_layer = i; run_opengl(); } else { overlayer->overlay(output, temp, 0, 0, output->get_w(), output->get_h(), 0, 0, output->get_w(), output->get_h(), 1, config.mode, NEAREST_NEIGHBOR); } } return 0; }