static void play_note2(Data *data, int time, note_t note){ //printf("Playing %f\n",note.pitch); Voice *voice = data->voices_not_playing; if(voice==NULL){ printf("no more free voices\n"); return; } RT_remove_voice(&data->voices_not_playing, voice); RT_add_voice(&data->voices_playing, voice); *(voice->myUI._gate_control) = 1.0f; *(voice->myUI._freq_control) = midi_to_hz(note.pitch); *(voice->myUI._gain_control) = velocity2gain(note.velocity); voice->note_num = note.pitch; voice->note_id = note.id; voice->seqblock = note.seqblock; voice->frames_since_stop = 0; voice->delta_pos_at_start = time; voice->delta_pos_at_end = -1; }
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; //printf("Playing %d\n",note_num); Voice *voice = data->voices_not_playing; if(voice==NULL){ printf("no more free voices\n"); return; } RT_remove_voice(&data->voices_not_playing, voice); RT_add_voice(&data->voices_playing, voice); //voice->dsp_instance->init((int)data->samplerate); *(voice->myUI._gate_control) = 1.0f; *(voice->myUI._freq_control) = midi_to_hz(note_num); *(voice->myUI._gain_control) = velocity2gain(volume); voice->note_num = note_num; voice->note_id = note_id; voice->frames_since_stop = 0; voice->delta_pos_at_start = time; voice->delta_pos_at_end = -1; }
static void set_note_pitch2(Data *data, int time, note_t note){ Voice *voice = data->voices_playing; //printf("Setting volume %f / %f\n",volume,velocity2gain(volume)); while(voice!=NULL){ if(is_note(note, voice->note_id, voice->seqblock)) *(voice->myUI._freq_control) = midi_to_hz(note.pitch); voice=voice->next; } }
static void set_note_pitch(struct SoundPlugin *plugin, int64_t time, float note_num, int64_t note_id, float pitch){ Data *data = (Data*)plugin->data; Voice *voice = data->voices_playing; //printf("Setting volume %f / %f\n",volume,velocity2gain(volume)); while(voice!=NULL){ if(voice->note_id==note_id) *(voice->myUI._freq_control) = midi_to_hz(pitch); voice=voice->next; } }
int main( int argc, const char ** argv ) { PaStreamParameters outputParameters; PaError pa_err; SF_INFO sfinfo; int i; for (i = 1; i < argc; i++) { if (!strncmp(argv[i], "-m", 2)) { mute = 1; } if (!strncmp(argv[i], "-o", 2)) { to_stdout = 1; } } gen_default_drums(); pa_err = Pa_Initialize(); outputParameters.device = Pa_GetDefaultOutputDevice(); outputParameters.channelCount = CHANNELS; outputParameters.sampleFormat = paFloat32; outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; pa_err = Pa_OpenStream( &stream, NULL, &outputParameters, SAMPLE_RATE, BUFFER_SIZE, paClipOff, audio_callback, NULL ); sfinfo.samplerate = SAMPLE_RATE; sfinfo.channels = CHANNELS; sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT; wave_output = sf_open( OUTPUT_FILE, SFM_WRITE, &sfinfo ); convert_buf = (int32_t*)malloc(SAMPLE_RATE * 4 * 2); srand( time( 0 ) ); bass_z = 0.0f; bass_freq = midi_to_hz( BASE_NOTE ); pa_err = Pa_StartStream( stream ); while( 1 ) Pa_Sleep( 10000 ); sf_close( wave_output ); pa_err = Pa_StopStream( stream ); pa_err = Pa_CloseStream( stream ); Pa_Terminate(); return 0; }
int main( void ) { PaStreamParameters outputParameters; PaError pa_err; SF_INFO sfinfo; signal( SIGINT, interrupt ); gen_default_drums(); pa_err = Pa_Initialize(); outputParameters.device = Pa_GetDefaultOutputDevice(); outputParameters.channelCount = CHANNELS; outputParameters.sampleFormat = paFloat32; outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; pa_err = Pa_OpenStream( &stream, NULL, &outputParameters, SAMPLE_RATE, BUFFER_SIZE, paClipOff, audio_callback, NULL ); sfinfo.samplerate = SAMPLE_RATE; sfinfo.channels = CHANNELS; sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT; wave_output = sf_open( OUTPUT_FILE, SFM_WRITE, &sfinfo ); srand( time( 0 ) ); bass_z = 0.0f; bass_freq = midi_to_hz( BASE_NOTE ); pa_err = Pa_StartStream( stream ); while( 1 ) Pa_Sleep( 1000 ); sf_close( wave_output ); pa_err = Pa_StopStream( stream ); pa_err = Pa_CloseStream( stream ); Pa_Terminate(); return 0; }
static void play_note(struct SoundPlugin *plugin, int64_t time, int note_num, float volume){ Data *data = (Data*)plugin->data; //printf("Playing %d\n",note_num); Voice *voice = data->voices_not_playing; if(voice==NULL){ printf("no more free voices\n"); return; } RT_remove_voice(&data->voices_not_playing, voice); RT_add_voice(&data->voices_playing, voice); *(voice->myUI._gate_control) = 1.0f; *(voice->myUI._freq_control) = midi_to_hz(note_num); *(voice->myUI._gain_control) = velocity2gain(volume); voice->note_num = note_num; }
void runSO_404( LV2_Handle arg, uint32_t nframes ) { so_404* so=(so_404*)arg; lv2_event_begin(&so->in_iterator,so->MidiIn); float* outbuffer=so->output; if(*so->controlmode_p >0) { so->cutoff=*so->cutoff_p; so->portamento=*so->portamento_p; so->release=*so->release_p; so->volume=*so->volume_p; so->envmod=*so->envmod_p; so->resonance=*so->resonance_p; } int i; for( i=0; i<nframes; i++ ) { while(lv2_event_is_valid(&so->in_iterator)) { uint8_t* data; LV2_Event* event= lv2_event_get(&so->in_iterator,&data); if (event->type == 0) { so->event_ref->lv2_event_unref(so->event_ref->callback_data, event); } else if(event->type==so->midi_event_id) { if(event->frames > i) { break; } else { const uint8_t* evt=(uint8_t*)data; if((evt[0]&MIDI_CHANNELMASK)==(int) (*so->channel_p)) { if((evt[0]&MIDI_COMMANDMASK)==MIDI_NOTEON) { unsigned int note = evt[1]; so->tfreq=midi_to_hz(note); if( so->noteson == 0 ) { so->freq = so->tfreq; so->amp=1.0; so->vel = ((float)evt[2]); so->env=so->vel/127.0; so->cdelay = 0; } so->noteson += 1; } else if((evt[0]&MIDI_COMMANDMASK)==MIDI_NOTEOFF ) { so->noteson -= 1; if(so->noteson<0) { so->noteson=0; } } else if((*so->controlmode_p<=0) && (evt[0]&MIDI_COMMANDMASK)==MIDI_CONTROL ) { unsigned int command_val=evt[2]; switch(evt[1]) { case 74: so->cutoff =command_val; break; case 65: so->portamento = command_val; break; case 72: so->release = command_val; break; case 7: so->volume = command_val; break; case 79: so->envmod = command_val; break; case 71: so->resonance = command_val; break; } } } } } lv2_event_increment(&so->in_iterator); } if( so->cdelay <= 0 ) { so->freq = ((so->portamento/127.0)*0.9)*so->freq + (1.0-((so->portamento/127.0)*0.9))*so->tfreq; if( so->noteson > 0 ) { so->amp *= 0.99; } else { so->amp *= 0.5; } so->env*=0.8+powf(so->release/127.0,0.25)/5.1; so->fcutoff = powf(so->cutoff/127.0,2.0)+powf(so->env,2.0)*powf(so->envmod/127.0,2.0); so->fcutoff = tanh(so->fcutoff); so->freso = powf(so->resonance/130.0,0.25); so->cdelay = so->samplerate/100; } so->cdelay--; float max = so->samplerate / so->freq; float sample = (so->phase/max)*(so->phase/max)-0.25; so->phase++; if( so->phase >= max ) { so->phase -= max; } if(so->vel>100) { sample*=so->env; } else { sample*=so->amp; } so->fpos += so->fspeed; so->fspeed *= so->freso; so->fspeed += (sample-so->fpos)*so->fcutoff; sample = so->fpos; sample = sample*0.5+so->lastsample*0.5; so->lastsample = sample; outbuffer[i] = sample * (so->volume/127.0); } }
static bool load_sample_with_libsndfile(Data *data, const wchar_t *filename){ SF_INFO sf_info; memset(&sf_info,0,sizeof(sf_info)); data->num_different_samples = 1; float *samples = load_interleaved_samples(filename, &sf_info); if(samples==NULL){ fprintf(stderr,"could not open file\n"); return false; } { int num_channels = sf_info.channels; printf("Num channels: %d\n",num_channels); if(num_channels > 2) // TODO num_channels = 2; int ch; for(ch=0;ch<num_channels;ch++){ Sample *sample = (Sample*)&data->samples[ch]; sample->num_frames = sf_info.frames; sample->sound = malloc(sizeof(float)*sample->num_frames); } int interleaved_pos=0; int i; for(i=0;i<sf_info.frames;i++){ for(ch=0;ch<sf_info.channels;ch++){ if(ch<2){ Sample *sample=(Sample*)&data->samples[ch]; sample->sound[i] = samples[interleaved_pos]; } interleaved_pos++; } } for(ch=0;ch<num_channels;ch++){ Sample *sample=(Sample*)&data->samples[ch]; set_legal_loop_points(sample,-1,-1); // By default, don't loop, but if set, loop all. if((sf_info.format&0xffff0000) == SF_FORMAT_WAV){ printf("format: 0x%x. sections: %d, num_frames: %d. SF_FORMAT_WAV: 0x%x. og: 0x%x\n",sf_info.format,sf_info.sections,(int)sf_info.frames,SF_FORMAT_WAV,sf_info.format&SF_FORMAT_WAV); set_wav_loop_points(sample,filename); } if(num_channels==1) sample->ch = -1; // i.e play the sample in both channels. else sample->ch = ch; int i; for(i=1;i<128;i++){ Note *note=(Note*)&data->notes[i]; note->num_samples = num_channels; note->samples[ch] = sample; sample->frequency_table[i] = sf_info.samplerate * midi_to_hz(i)/midi_to_hz(48); //printf("%d: %f, data: %f, sample: %f, midifreq: %f\n",i,sample->samplerate,(float)data->samplerate,(float)sf_info.samplerate,midi_to_hz(i)); } } } return true; }
static double get_ratio(int sample_note_num, int play_note_num){ return midi_to_hz(sample_note_num) / midi_to_hz(play_note_num); }
static int audio_callback( const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData ) { int i; float *out = (float*)outputBuffer; float b, d, f, mod; int beat; float v; for( i = 0; i < framesPerBuffer; i++ ) { d = 0; beat = global_frame % ( SAMPLE_RATE / ( DEFAULT_BPM / 60 ) / 4 ); if( beat == 0 ) { if( beat_count % 4 == 0 ) bass_lfofreq = ((float)DEFAULT_BPM/60.0f) * flt_freq[ rand()%4 ]; if( rand()%RANDOM_NOTE_CHANGE_CHANCE == 0 ) { bass_freq = midi_to_hz( BASE_NOTE + minor_scale[ rand()%7 ] + ((rand()%RANDOM_OCTAVE_JUMP_CHANCE==0)?12:0) ); } if( ( beat_count % 4 == 0 ) && ( rand()%RANDOM_GLITCH_CHANCE == 0 ) ) { bass_fmindex = (float)( rand()%999 + 1 ); } if( ( beat_count % 4 == 0 ) && ( rand()%RANDOM_GLITCH_RETURN_CHANCE == 0 ) ) { bass_fmindex = 0.0f; } if( rand()%RANDOM_MODULATION == 0 ) { bass_fmmod = (float)( rand()%3 + 1 ); } if( beat_count % 16 == 0 ) bd_time = 0; if( beat_count % 16 == 8 ) { if( rand()%RANDOM_SNARE_SILENCE_CHANCE == 0 ) bass_vol = 0.0f; sd_time = 0; } if( ( beat_count % 16 == 10 ) && ( rand()%RANDOM_SNARE_CHANCE == 0 ) ) sd_time = 0; if( beat_count % 16 == 12 ) bass_vol = 1.0f; if( beat_count % 16 == 6 ) bd_time = 0; if( beat_count % 2 == 0 ) hh_time = 0; beat_count++; } if( bd_time >= 0 ) { d = bd[bd_time++]; if( bd_time > SAMPLE_RATE ) bd_time = -1; } if( sd_time >= 0 ) { d = d * 0.8f + sd[sd_time++]; if( sd_time > SAMPLE_RATE ) sd_time = -1; } if( hh_time >= 0 ) { d = d * 0.8f + hh[hh_time++] * 0.05f; if( hh_time > SAMPLE_RATE ) hh_time = -1; } bass_lfoval = sin( 2.0 * M_PI * bass_lfofreq * (float)global_frame / (float)SAMPLE_RATE ); bass_lfoval = bass_lfoval/100.0f + 0.99f; mod = sin( 2.0 * M_PI * bass_fmmod * bass_freq * (float)global_frame / (float)SAMPLE_RATE ); b = sgn( sin( 2.0 * M_PI * ( bass_freq * (float)global_frame / (float)SAMPLE_RATE ) + mod * bass_fmindex ) ); bass_z = bass_lfoval * bass_z + ( 1.0f - bass_lfoval ) * b; v = 0.3f; out[i] = bass_vol * bass_z * v + d * ( 1.0f-v ); if( out[i] > 1.0f ) out[i] = 1.0f; if( out[i] < -1.0f ) out[i] = -1.0f; global_frame++; } sf_write_float( wave_output, out, framesPerBuffer ); if (to_stdout) { for (i = 0; i < framesPerBuffer; i++) { double f = (double)out[i]; convert_buf[i] = (int32_t)(f * 0x7fffffffL); } write(STDOUT_FILENO, convert_buf, framesPerBuffer * 4); } if (mute) memset(out, 0, sizeof(float) * framesPerBuffer); return paContinue; }
/* main function that makes the dubstep sound */ static int audio_callback( const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData ) { int i; float *out = (float*)outputBuffer; float b, d, f, mod; int beat; float v; for( i = 0; i < framesPerBuffer; i++ ) { d = 0; beat = global_frame % ( SAMPLE_RATE / ( DEFAULT_BPM / 60 ) / 4 ); /* if the stream has hit a beat */ if( beat == 0 ) { /* 4 beats is half a measure; alter the filter's LFO */ if( beat_count % 4 == 0 ) bass_lfofreq = ((float)DEFAULT_BPM/60.0f) * flt_freq[ rand()%4 ]; /* change the note by choosing another from the provided scale */ if( rand()%RANDOM_NOTE_CHANGE_CHANCE == 0 ) { bass_freq = midi_to_hz( BASE_NOTE + minor_scale[ rand()%7 ] + ((rand()%RANDOM_OCTAVE_JUMP_CHANCE==0)?12:0) ); } /* alter the FM index (modulator amplitude), to add overtones to the bassline, thus creating the 'glitched' sound */ if( ( beat_count % 4 == 0 ) && ( rand()%RANDOM_GLITCH_CHANCE == 0 ) ) { bass_fmindex = (float)( rand()%999 + 1 ); } /* reset the FM index to return to the normal square bass sound */ if( ( beat_count % 4 == 0 ) && ( rand()%RANDOM_GLITCH_RETURN_CHANCE == 0 ) ) { bass_fmindex = 0.0f; } /* alter the FM mod (modulator frequency multiplier) */ if( rand()%RANDOM_MODULATION == 0 ) { bass_fmmod = (float)( rand()%3 + 1 ); } /* a bassdrum hits every two measures */ if( beat_count % 16 == 0 ) bd_time = 0; /* sometimes, the snare won't trigger */ if( beat_count % 16 == 8 ) { if( rand()%RANDOM_SNARE_SILENCE_CHANCE == 0 ) bass_vol = 0.0f; sd_time = 0; } /* trigger a snare drum on the 10th beat of two measures combined */ if( ( beat_count % 16 == 10 ) && ( rand()%RANDOM_SNARE_CHANCE == 0 ) ) sd_time = 0; /* reset the volume of the bassline, if it has been previously diminished, to create the impression of a compressor */ if( beat_count % 16 == 12 ) bass_vol = 1.0f; /* trigger a bass drum */ if( beat_count % 16 == 6 ) bd_time = 0; /* trigger a hihat */ if( beat_count % 2 == 0 ) hh_time = 0; beat_count++; } /* advance sample counters and mix the drum channel */ if( bd_time >= 0 ) { d = bd[bd_time++]; if( bd_time > SAMPLE_RATE ) bd_time = -1; } if( sd_time >= 0 ) { d = d * 0.8f + sd[sd_time++]; if( sd_time > SAMPLE_RATE ) sd_time = -1; } if( hh_time >= 0 ) { d = d * 0.8f + hh[hh_time++] * 0.05f; if( hh_time > SAMPLE_RATE ) hh_time = -1; } /* compute the LFO value */ bass_lfoval = sin( 2.0 * M_PI * bass_lfofreq * (float)global_frame / (float)SAMPLE_RATE ); /* the LFO value is in range 0.00 .. 0.01 */ bass_lfoval = bass_lfoval/100.0f + 0.99f; /* compute the modulator */ mod = sin( 2.0 * M_PI * bass_fmmod * bass_freq * (float)global_frame / (float)SAMPLE_RATE ); /* compute the bassline */ b = sgn( sin( 2.0 * M_PI * ( bass_freq * (float)global_frame / (float)SAMPLE_RATE ) + mod * bass_fmindex ) ); /* process the bassline through a lowpass filter */ bass_z = bass_lfoval * bass_z + ( 1.0f - bass_lfoval ) * b; v = 0.3f; /* final mix of the two tracks */ out[i] = bass_vol * bass_z * v + d * ( 1.0f-v ); if( out[i] > 1.0f ) out[i] = 1.0f; if( out[i] < -1.0f ) out[i] = -1.0f; global_frame++; } sf_write_float( wave_output, out, framesPerBuffer ); return paContinue; }
static bool load_sf2_instrument(Data *data, const wchar_t *filename, int preset_bag_number, bool set_loop_on_off){ EVENTLOG_add_event(talloc_format("load_sf2_instrument -%S-", filename)); hash_t *info = SF2_get_info(filename); if(info==NULL){ GFX_Message(NULL, "Unable to open soundfont file \"%S\"\n", filename); return false; } //HASH_save(info,stdout); hash_t *sample_infos = HASH_get_hash(info,"samples"); hash_t *presets = HASH_get_hash(info,"presets"); hash_t *preset = HASH_get_hash_at(presets, "", preset_bag_number); if(preset==NULL){ GFX_Message(NULL, "No such preset number %d in instrument \"%S\"\n", preset_bag_number, filename); return false; } int bank_num = HASH_get_int32(preset,"bank"); hash_t *instrument = NULL; // Try to find an instrument from the region. A preset may use several instruments, but that's not supported yet. We just use the first and best/worst. { hash_t *instruments = HASH_get_hash(info,"instruments"); hash_t *regions = HASH_get_hash(preset,"regions"); int i; for(i=0;i<HASH_get_array_size(regions, "");i++){ hash_t *region = HASH_get_hash_at(regions,"",i); if(HASH_has_key(region,"instrument")==true){ instrument = HASH_get_hash(instruments,HASH_get_chars(region,"instrument")); break; } } } if(instrument==NULL){ GFX_Message(NULL, "load_sf2_instrument: Preset \"%S\" (bank %d / preset %d) in \"%S\" doesn't point to an instrument\n", HASH_get_string(preset,"name"), bank_num, HASH_get_int32(preset,"num"), filename ); return false; } hash_t *regions = HASH_get_hash(instrument, "regions"); for(int i=0;i<128;i++){ Note *note = new Note; data->notes[i] = note; data->note_storage.push_back(note); } int num_samples=0; int i; for(i=0;i<HASH_get_array_size(regions, "");i++){ hash_t *region = HASH_get_hash_at(regions,"",i); const char *sample_name = HASH_get_chars(region, "sample_name"); if(strcmp(sample_name,"<no sample!>")){ hash_t *sample_info = HASH_get_hash(sample_infos, sample_name); int sample_num = HASH_get_int32(sample_info,"num"); Sample &sample = data->samples[num_samples++]; new (&sample) Sample(); sample.data = data; sample.volume = 1.0f; sample.num_frames = HASH_get_int(sample_info,"num_frames"); set_legal_loop_points(sample,-1,-1, set_loop_on_off); // By default, loop all. set_legal_loop_points(sample, HASH_get_int(sample_info,"loop start"), HASH_get_int(sample_info,"loop end"), set_loop_on_off ); printf("Loop start / end: %d %d\n",(int)sample.loop_start,(int)sample.loop_end); { sample.ch = -1; const char *type = HASH_get_chars(sample_info,"type"); if(!strcmp(type,"Left Sample") || !strcmp(type,"ROM Left Sample")) sample.ch = 0; if(!strcmp(type,"Right Sample") || !strcmp(type,"ROM Right Sample")) sample.ch = 1; } sample.sound = SF2_load_sample(filename, sample_num); int root_key = HASH_get_int32(region, "root key"); int coarsetune = HASH_get_int32(region, "coarse tune"); int finetune = HASH_get_int32(region, "fine tune"); printf("root: %d, coarse: %d, fine: %d, sample pitch: %d\n",root_key,coarsetune,finetune,(int)HASH_get_int(sample_info,"pitch")); int note; for(note=0;note<128;note++) if(HASH_get_int(sample_info,"pitch")==255) sample.frequency_table[note] = HASH_get_int(sample_info, "samplerate"); else sample.frequency_table[note] = HASH_get_int(sample_info, "samplerate") * midi_to_hz(note+coarsetune+(float)finetune/100.0) / midi_to_hz(root_key); int note_num; for(note_num=HASH_get_int32(region,"key start");note_num<=HASH_get_int32(region,"key end");note_num++){ Note *note = const_cast<Note*>(data->notes[note_num]); note->samples.push_back(&sample); //printf("%d: %f. middle_note: %d, finetune: %f. Sample: %p. Frequency: %f\n",i,dest->ratio,dest->middle_note,dest->finetune,dest->interleaved_samples,get_frequency(i,dest->finetune)); } } } // Optimize data->notes so that as few Note objects as possible are used (better for cache) for(int i=0;i<128;i++){ Note *old_note = const_cast<Note*>(data->notes[i]); old_note->sort_samples(); for(int i2=0;i2<i;i2++){ if(data->notes[i]->is_equal(data->notes[i2])){ data->notes[i] = data->notes[i2]; data->note_storage.remove(old_note); delete old_note; printf(" Load SF2: Move notes %d to %d. Size of note_storage: %d\n", i, i2, data->note_storage.size()); break; } } } return true; }