// Think I found this pan calculation method in the ardour source many years ago. // TODO: Optimize panning when smoothing is necessary. void SMOOTH_apply_pan(Smooth *smooth, float **sound, int num_channels, int num_frames){ R_ASSERT(smooth->target_audio_will_be_modified==true); int i; if(num_channels>=2){ float *sound0 = sound[0]; float *sound1 = sound[1]; if(is_smoothing_necessary(smooth)==true){ //fprintf(stderr,"s1\n"); Panvals pan_start = das_get_pan_vals_vector(scale(smooth->values[0],0,1,-1,1),2); //fprintf(stderr,"s2\n"); Panvals pan_end = das_get_pan_vals_vector(scale(smooth->values[num_frames-1],0,1,-1,1),2); //fprintf(stderr,"s3\n"); for(i=0;i<num_frames;i++) { float sound0i = sound0[i]; float sound1i = sound1[i]; sound0[i] = sound0i*scale(i,0,num_frames,pan_start.vals[0][0],pan_end.vals[0][0]) + sound1i*scale(i,0,num_frames,pan_start.vals[1][0],pan_end.vals[1][0]); sound1[i] = sound0i*scale(i,0,num_frames,pan_start.vals[0][1],pan_end.vals[0][1]) + sound1i*scale(i,0,num_frames,pan_start.vals[1][1],pan_end.vals[1][1]); } } else { if(smooth->value!=0.5f){ Panvals pan = get_pan_vals_vector(scale(smooth->value,0,1,-1,1), 2); #if 1 if(smooth->value < 0.5f){ for(i=0;i<num_frames;i++) sound0[i] += sound1[i]*pan.vals[1][0]; for(i=0;i<num_frames;i++) sound1[i] *= pan.vals[1][1]; } else { for(i=0;i<num_frames;i++) sound1[i] += sound0[i]*pan.vals[0][1]; for(i=0;i<num_frames;i++) sound0[i] *= pan.vals[0][0]; } #else // Same, but perhaps a bit slower. for(i=0;i<num_frames;i++) { float sound0i = sound0[i]; float sound1i = sound1[i]; sound0[i] = sound0i*pan.vals[0][0] + sound1i*pan.vals[1][0]; sound1[i] = sound0i*pan.vals[0][1] + sound1i*pan.vals[1][1]; } #endif } } } }
static void play_note(struct SoundPlugin *plugin, int64_t time, float note_num, int64_t note_id, float volume, float pan){ Data *data = (Data*)plugin->data; //fprintf(stderr,"playing note %d. Pitch: %d, time: %d\n",(int)note_id,(int)note_num,(int)time); const Note *note = &data->notes[(int)note_num]; int i; for(i=0;i<note->num_samples;i++){ if(data->voices_not_playing==NULL){ printf("No more free voices\n"); return; } Voice *voice = data->voices_not_playing; RT_remove_voice(&data->voices_not_playing, voice); RT_add_voice(&data->voices_playing, voice); voice->last_finetune_value = data->finetune; voice->note_num = note_num; voice->note_id = note_id; voice->start_volume = velocity2gain(volume); voice->end_volume = voice->start_volume; voice->start_pitch = note_num; voice->end_pitch = note_num; voice->sample = note->samples[i]; if(data->loop_onoff==true && voice->sample->loop_end > voice->sample->loop_start) voice->pos=scale(data->startpos, // set startpos between 0 and loop_end 0,1, 0,voice->sample->loop_end); else voice->pos=scale(data->startpos, // set startpos between 0 and sound length 0,1, 0,voice->sample->num_frames); voice->pan = get_pan_vals_vector(pan,voice->sample->ch==-1?1:2); RESAMPLER_reset(voice->resampler); ADSR_reset(voice->adsr); ADSR_set_adsr(voice->adsr, data->a, data->h, data->d, data->s, data->r); voice->delta_pos_at_start=time; voice->delta_pos_at_end=-1; voice->is_fading_out=false; } }
static void play_note(struct SoundPlugin *plugin, int64_t time, float note_num, int64_t note_id, float volume,float pan){ Data *data = (Data*)plugin->data; if(data->voices_not_playing==NULL){ printf("No more free voices\n"); return; } Voice *voice = data->voices_not_playing; RT_remove_voice(&data->voices_not_playing, voice); RT_add_voice(&data->voices_playing, voice); voicd->note_id = note_id; voice->velocity = volume; voice->pan = get_pan_vals_vector(pan,2); voice->delta_pos_at_start=time; voice->delta_pos_at_end=-1; voice->audio = data->audio[0] }
static int get_peaks(struct SoundPlugin *plugin, float note_num, int ch, float das_pan, int64_t start_time, int64_t end_time, float *min_value, float *max_value ) { Data *data = (Data*)plugin->data; if(ch==-1){ int i; for(i=0;i<MAX_NUM_SAMPLES;i++){ Sample *sample=(Sample*)&data->samples[i]; if(sample->sound!=NULL){ if(sample->ch==1) return 2; } } return 1; } int start_frame = time_to_frame(data, start_time, note_num); int end_frame = time_to_frame(data, end_time, note_num); { const Note *note=&data->notes[(int)note_num]; float min=0.0f; float max=0.0f; int samplenum; for(samplenum=0;samplenum<note->num_samples;samplenum++){ const Sample *sample=note->samples[samplenum]; Panvals pan = get_pan_vals_vector(das_pan, sample->ch==-1 ? 1 : 2); int input_channel = sample->ch==-1 ? 0 : sample->ch; float panval = pan.vals[input_channel][ch]; if(panval>0.0f){ float min2; float max2; get_peaks_from_sample(sample, start_frame, end_frame, &min2, &max2); min2 *= panval; max2 *= panval; if(min2<min) min=min2; if(max2>max) max=max2; } } *min_value = min; *max_value = max; } apply_adsr_to_peak(data, (start_time+end_time)/2, min_value, max_value); return 2; }