diff --git a/Makefile.am b/Makefile.am index cf37019e0..37870547c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -196,6 +196,7 @@ lmms_SOURCES = \ $(srcdir)/src/lib/embed.cpp \ $(srcdir)/src/lib/mmp.cpp \ $(srcdir)/src/lib/oscillator.cpp \ + $(srcdir)/src/lib/drumsynth.cpp \ $(srcdir)/src/lib/sample_buffer.cpp \ $(srcdir)/src/lib/string_pair_drag.cpp \ $(srcdir)/src/midi/midi_alsa_raw.cpp \ @@ -298,6 +299,7 @@ lmms_SOURCES = \ $(srcdir)/include/track_container.h \ $(srcdir)/include/bb_track.h \ $(srcdir)/include/sample_track.h \ + $(srcdir)/include/drumsynth.h \ $(srcdir)/include/sample_buffer.h \ $(srcdir)/include/name_label.h \ $(srcdir)/include/play_handle.h \ diff --git a/configure.in b/configure.in index ede0a7f92..83f03522c 100644 --- a/configure.in +++ b/configure.in @@ -596,6 +596,32 @@ AC_CONFIG_FILES([Makefile data/samples/bassloopes/Makefile data/samples/beats/Makefile data/samples/drums/Makefile + data/samples/drumsynth/Makefile + data/samples/drumsynth/acoustic/Makefile + data/samples/drumsynth/cr78/Makefile + data/samples/drumsynth/cr8000/Makefile + data/samples/drumsynth/effects/Makefile + data/samples/drumsynth/electro/Makefile + data/samples/drumsynth/farfisa/Makefile + data/samples/drumsynth/ferraro/Makefile + data/samples/drumsynth/instrument/Makefile + data/samples/drumsynth/jorgensohn/Makefile + data/samples/drumsynth/latin/Makefile + data/samples/drumsynth/linn/Makefile + data/samples/drumsynth/magnetboy/Makefile + data/samples/drumsynth/misc/Makefile + data/samples/drumsynth/misc_bass/Makefile + data/samples/drumsynth/misc_claps/Makefile + data/samples/drumsynth/misc_electro/Makefile + data/samples/drumsynth/misc_fx/Makefile + data/samples/drumsynth/misc_hats/Makefile + data/samples/drumsynth/misc_perc/Makefile + data/samples/drumsynth/misc_synth/Makefile + data/samples/drumsynth/r_b/Makefile + data/samples/drumsynth/tr606/Makefile + data/samples/drumsynth/tr77/Makefile + data/samples/drumsynth/tr808/Makefile + data/samples/drumsynth/tr909/Makefile data/samples/effects/Makefile data/samples/instruments/Makefile data/samples/latin/Makefile diff --git a/data/samples/Makefile.am b/data/samples/Makefile.am index 81807e605..51b7e5b82 100644 --- a/data/samples/Makefile.am +++ b/data/samples/Makefile.am @@ -1,2 +1,2 @@ -SUBDIRS = basses bassloopes beats drums effects instruments latin misc shapes stringsnpads +SUBDIRS = basses bassloopes beats drums drumsynth effects instruments latin misc shapes stringsnpads diff --git a/include/sample_buffer.h b/include/sample_buffer.h index dd033abaa..e231b9a9f 100644 --- a/include/sample_buffer.h +++ b/include/sample_buffer.h @@ -249,6 +249,11 @@ private: ch_cnt_t & _channels, sample_rate_t & _sample_rate ); #endif + f_cnt_t FASTCALL decodeSampleDS( const char * _f, + int_sample_t * & _buf, + ch_cnt_t & _channels, + sample_rate_t & _sample_rate ); + QString m_audioFile; sampleFrame * m_origData; diff --git a/plugins/audio_file_processor/audio_file_processor.cpp b/plugins/audio_file_processor/audio_file_processor.cpp index 6ab09416c..6fd6d6207 100644 --- a/plugins/audio_file_processor/audio_file_processor.cpp +++ b/plugins/audio_file_processor/audio_file_processor.cpp @@ -724,8 +724,8 @@ const QStringList & audioFileProcessor::subPluginFeatures::supported_extensions( void ) { static QStringList extensions = QStringList() - << "wav" << "ogg" << "spx" << "au" << "voc" - << "aif" << "aiff" << "flac" << "raw"; + << "wav" << "ogg" << "ds" << "spx" << "au" + << "voc" << "aif" << "aiff" << "flac" << "raw"; return( extensions ); } diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index fab44cae5..5d0cf3db3 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -127,7 +127,7 @@ void lb302Filter::recalc() void lb302Filter::envRecalc() { - vcf_c0 *= fs->envdecay; // Filter Decay. vcf_decay is adjusted for Hz and ENVINC + vcf_c0 *= fs->envdecay; // Filter Decay. vcf_decay is already adjusted for Hz and ENVINC // vcf_rescoeff = exp(-1.20 + 3.455*(fs->reso)); moved above }; @@ -250,9 +250,7 @@ void lb302Filter3Pole::envRecalc() w = vcf_e0 + vcf_c0; // e0 is adjusted for Hz and doesn't need ENVINC k = (fs->cutoff > 0.975)?0.975:fs->cutoff; kfco = 50.f+(k)*((2300.f-1600.f*(fs->envmod))+(w)*(700.f+1500.f*(k)+(1500.f+(k)*(44100.f/2.f-6000.f))*(fs->envmod))); - //+iacc*(.3+.7*kfco*kenvmod)*kaccent*kaccurve*2000 - - + //+iacc*(.3+.7*kfco*kenvmod)*kaccent*kaccurve*2000 The accent code #ifdef LB_24_IGNORE_ENVELOPE @@ -270,7 +268,7 @@ void lb302Filter3Pole::envRecalc() #else kres = (((fs->reso))) * (((-2.7079*kp1 + 10.963)*kp1 - 14.934)*kp1 + 8.4974); #endif - value = 1.0+( (fs->dist) *(1.5 + 2.0*kres*(1.0-kfcn))); // ENVMOD was DIST*/ + value = 1.0+( (fs->dist) *(1.5 + 2.0*kres*(1.0-kfcn))); // ENVMOD was DIST } float lb302Filter3Pole::process(const float& samp) @@ -317,7 +315,22 @@ void lb302Filter3Pole::setState(const lb302FilterState* fs) // lb302Synth::lb302Synth( instrumentTrack * _channel_track ) : - instrument( _channel_track, &lb302_plugin_descriptor ) + instrument( _channel_track, &lb302_plugin_descriptor ), + vco_shape( SAWTOOTH ), + vco_inc( 0.0 ), + vco_c( 0 ), + vco_k( 0 ), + vco_detune( 0 ), + vco_slide( 0 ), + vco_slideinc( 0 ), + vco_slidebase( 0 ), + vcf_envpos( ENVINC ), + vca_a0( 0.5 ), + vca_mode( 3 ), + vca_a( 0 ), + //vca_attack( 1.0 - 0.94406088 ), + vca_attack( 1.0 - 0.96406088 ), + vca_decay( 0.99897516 ) { // GUI @@ -353,7 +366,7 @@ lb302Synth::lb302Synth( instrumentTrack * _channel_track ) : vcf_dec_knob->setHintText( tr( "Decay:" ) + " ", "" ); vcf_dec_knob->setLabel( tr("DEC") ); - slideToggle = new ledCheckBox( "Slide", this, + slideToggle = new ledCheckBox( "Slide", this, tr( "Slide" ), _channel_track ); slideToggle->move( 10, 180 ); @@ -447,36 +460,11 @@ lb302Synth::lb302Synth( instrumentTrack * _channel_track ) : setErasePixmap( PLUGIN_NAME::getIconPixmap( "artwork" ) ); #endif - // SYNTH - - vco_inc = 0.0; - vco_c = 0; - vco_k = 0; - - vco_slide = 0; vco_slideinc = 0; - vco_slidebase = 0; - fs.cutoff = 0; fs.envmod = 0; fs.reso = 0; fs.envdecay = 0; fs.dist = 0; - vcf_envpos = ENVINC; - vco_detune = 0; - - vca_mode = 3; vca_a = 0; // Start VCA on an attack. - - //vca_attack = 1.0 - 0.94406088; - vca_attack = 1.0 - 0.96406088; - vca_decay = 0.99897516; - - vco_shape = SAWTOOTH; - - vca_a0 = 0.5; // Experimenting between original (0.5) and 1.0 - vca_a = 9; - vca_mode = 3; - - vcf = new lb302FilterIIR2(&fs); use_hold_note = false; sample_cnt = 0; @@ -484,16 +472,28 @@ lb302Synth::lb302Synth( instrumentTrack * _channel_track ) : catch_frame = 0; catch_decay = 0; - recalcFilter(); + framesPerPeriod = engine::getMixer()->framesPerPeriod(); lastFramesPlayed = 1; // because we subtract 1 later last_offset = 0; - period_states = NULL; - period_states_cnt = 0; + + vcf = new lb302FilterIIR2(&fs); + recalcFilter(); filterChanged(0.0); detuneChanged(0.0); + + period_states_cnt = 0; + period_states = new lb302State[framesPerPeriod]; + for (int i=0; i < framesPerPeriod; i++) { + period_states[i].vco_c = vco_c; + period_states[i].vca_a = vca_a; + period_states[i].vca_mode = vca_mode; + period_states[i].sample_cnt = sample_cnt; + vcf->getState(&period_states[i].fs); + } + } @@ -559,7 +559,7 @@ void lb302Synth::filterChanged( float ) float d = 0.2 + (2.3*vcf_dec_knob->value()); d*=LB_HZ; // d *= smpl rate - fs.envdecay = pow(0.1, 1.0/d * ENVINC); // decay is 0.1 to the 1/d * ENVINC + fs.envdecay = pow(0.1, 1.0/d * ENVINC); // decay is 0.1 to the 1/d * ENVINC // vcf_envdecay is now adjusted for both // sampling rate and ENVINC recalcFilter(); @@ -618,7 +618,7 @@ QString lb302Synth::nodeName( void ) const return( lb302_plugin_descriptor.name ); } -// OBSOLETE. Break apart once we get Q_OBJECT to work. >:[ +// OBSOLETE void lb302Synth::recalcFilter() { vcf->recalc(); @@ -636,29 +636,14 @@ void lb302Synth::recalcFilter() vcf_envpos = ENVINC; // Trigger filter update in process() } -inline int MIN(int a, int b) { - return (a= ENVINC) { vcf->envRecalc(); @@ -669,15 +654,12 @@ int lb302Synth::process(sampleFrame *outbuf, const Uint32 size) vco_inc=vco_slidebase-vco_slide; // Calculate coeff from dec_knob on knob change. vco_slide*= 0.9+(slide_dec_knob->value()*0.0999); // TODO: Adjust for Hz and ENVINC - } } sample_cnt++; vcf_envpos++; - float old_vco_k = vco_k; - bool looking; int decay_frames = 128; // update vco @@ -695,7 +677,6 @@ int lb302Synth::process(sampleFrame *outbuf, const Uint32 size) } } - switch(int(rint(wave_knob->value()))) { case 0: vco_shape = SAWTOOTH; break; case 1: vco_shape = INVERTED_SAWTOOTH; break; @@ -709,51 +690,46 @@ int lb302Synth::process(sampleFrame *outbuf, const Uint32 size) // add vco_shape_param the changes the shape of each curve. // merge sawtooths with triangle and square with round square? switch (vco_shape) { - case SAWTOOTH: // p0: curviness of line - vco_k = vco_c; // Is this sawtooth backwards? + case SAWTOOTH: // p0: curviness of line + vco_k = vco_c; // Is this sawtooth backwards? break; case INVERTED_SAWTOOTH: // p0: curviness of line - vco_k = -vco_c; // Is this sawtooth backwards? + vco_k = -vco_c; // Is this sawtooth backwards? break; // TODO: I think TRIANGLE is broken. - case TRIANGLE: // p0: duty rev.saw<->triangle<->saw p1: curviness + case TRIANGLE: // p0: duty rev.saw<->triangle<->saw p1: curviness vco_k = (vco_c*2.0)+0.5; if (vco_k>0.5) vco_k = 1.0-vco_k; break; - case SQUARE: // p0: slope of top + case SQUARE: // p0: slope of top vco_k = (vco_c<0)?0.5:-0.5; break; - case ROUND_SQUARE: // p0: width of round + case ROUND_SQUARE: // p0: width of round vco_k = (vco_c<0)?(sqrtf(1-(vco_c*vco_c*4))-0.5):-0.5; break; - case MOOG: // Maybe the fall should be exponential/sinsoidal instead of quadric. - // [-0.5, 0]: Rise, [0,0.25]: Slope down, [0.25,0.5]: Low + case MOOG: // Maybe the fall should be exponential/sinsoidal instead of quadric. + // [-0.5, 0]: Rise, [0,0.25]: Slope down, [0.25,0.5]: Low vco_k = (vco_c*2.0)+0.5; if (vco_k>1.0) vco_k = -0.5 ; else if (vco_k>0.5) { w = 2.0*(vco_k-0.5)-1.0; vco_k = 0.5 - sqrtf(1.0-(w*w)); } - vco_k *= 2.0; // MOOG wave gets filtered away + vco_k *= 2.0; // MOOG wave gets filtered away break; } - //vca_a = 0.5; // Write out samples. #ifdef LB_FILTERED samp = vcf->process(vco_k)*2.0*vca_a; #else samp = vco_k*vca_a; #endif - /* - float releaseFrames = desiredReleaseFrames(); - samp *= (releaseFrames - catch_decay)/releaseFrames; - */ samp *= (float)(decay_frames - catch_decay)/(float)decay_frames; for(int c=0; cframesPerPeriod(); ///=== WEIRD CODE FOR MONOPHONIC BEHAVIOUR - BEGIN === /// @@ -929,17 +905,6 @@ void lb302Synth::playNote( notePlayHandle * _n, bool ) ///=== WEIRD CODE FOR MONOPHONIC BEHAVIOUR - END === /// /// Malloc our period history buffer - if (period_states == NULL) { - period_states = new lb302State[framesPerPeriod]; - - for (int i=0; i < framesPerPeriod; i++) { - period_states[i].vco_c = vco_c; - period_states[i].vca_a = vca_a; // Doesn't change anything (currently) - period_states[i].vca_mode = vca_mode; // Doesn't change anything (currently) - period_states[i].sample_cnt = sample_cnt; // Doesn't change anything (currently) - vcf->getState(&period_states[i].fs); - } - } // now resume at the proper position and process as usual @@ -968,20 +933,12 @@ void lb302Synth::playNote( notePlayHandle * _n, bool ) if(deadToggle->value()==0 && decay_note) { #ifdef LB_DECAY if (catch_decay < 1) { - // BEGIN NOT SURE OF... - //lb302State *st = &period_states[period_states_cnt-1]; - //vca_a = st->vca_a; - //sample_cnt = st->sample_cnt; - // END NOT SURE OF - // Reserve this note for retrigger in process() hold_note.vco_inc = _n->frequency()*vco_detune/LB_HZ; // TODO: Use actual sampling rate. hold_note.dead = deadToggle->value(); use_hold_note = true; catch_decay = 1; } - else { - } #else lb302Note note; note.vco_inc = _n->frequency()*vco_detune/LB_HZ; // TODO: Use actual sampling rate. diff --git a/plugins/lb302/lb302.h b/plugins/lb302/lb302.h index 0311394e7..87cc78fd7 100644 --- a/plugins/lb302/lb302.h +++ b/plugins/lb302/lb302.h @@ -283,7 +283,9 @@ private: int sample_cnt; int last_offset; + + int framesPerPeriod; lb302State *period_states; int period_states_cnt; diff --git a/src/lib/sample_buffer.cpp b/src/lib/sample_buffer.cpp index a33c52f6e..d1c715d9c 100644 --- a/src/lib/sample_buffer.cpp +++ b/src/lib/sample_buffer.cpp @@ -88,6 +88,8 @@ #include "base64.h" #include "debug.h" +#include "drumsynth.h" + #ifndef QT4 @@ -258,6 +260,12 @@ void sampleBuffer::update( bool _keep_settings ) samplerate ); } #endif + if( m_frames == 0 ) + { + m_frames = decodeSampleDS( f, buf, channels, + samplerate ); + } + if( m_frames > 0 && buf != NULL ) { // following code transforms int-samples into @@ -489,7 +497,18 @@ long qfileTellCallback( void * _udata ) } +f_cnt_t sampleBuffer::decodeSampleDS( const char * _f, + int_sample_t * & _buf, + ch_cnt_t & _channels, + sample_rate_t & _samplerate ) +{ + f_cnt_t frames = 0; + DrumSynth ds; + frames = ds.GetDSFileSamples( _f, _buf, _channels); + + return frames; +} f_cnt_t sampleBuffer::decodeSampleOGGVorbis( const char * _f, int_sample_t * & _buf, @@ -896,10 +915,11 @@ QString sampleBuffer::openAudioFile( void ) const // set filters #ifdef QT4 QStringList types; - types << tr( "All Audio-Files (*.wav *.ogg *.flac *.spx *.voc *.aif " + types << tr( "All Audio-Files (*.wav *.ogg *.flac *.ds *.spx *.voc *.aif " "*.aiff *.au *.raw)" ) << tr( "Wave-Files (*.wav)" ) << tr( "OGG-Files (*.ogg)" ) + << tr( "DrumSynth-Files (*.ds)" ) << tr( "FLAC-Files (*.flac)" ) << tr( "SPEEX-Files (*.spx)" ) //<< tr( "MP3-Files (*.mp3)" ) @@ -912,10 +932,11 @@ QString sampleBuffer::openAudioFile( void ) const ; ofd.setFilters( types ); #else - ofd.addFilter( tr( "All Audio-Files (*.wav *.ogg *.flac *.spx *.voc " + ofd.addFilter( tr( "All Audio-Files (*.wav *.ogg *.flac *.ds *.spx *.voc " "*.aif *.aiff *.au *.raw)" ) ); ofd.addFilter( tr( "Wave-Files (*.wav)" ) ); ofd.addFilter( tr( "OGG-Files (*.ogg)" ) ); + ofd.addFilter( tr( "DrumSynth-Files (*.ds)" ) ); ofd.addFilter( tr( "FLAC-Files (*.flac)" ) ); ofd.addFilter( tr( "SPEEX-Files (*.spx)" ) ); //ofd.addFilter (tr("MP3-Files (*.mp3)")); @@ -925,7 +946,7 @@ QString sampleBuffer::openAudioFile( void ) const ofd.addFilter( tr( "AU-Files (*.au)" ) ); ofd.addFilter( tr( "RAW-Files (*.raw)" ) ); //ofd.addFilter (tr("MOD-Files (*.mod)")); - ofd.setSelectedFilter( tr( "All Audio-Files (*.wav *.ogg *.flac *.spx " + ofd.setSelectedFilter( tr( "All Audio-Files (*.wav *.ogg *.ds *.flac *.spx " "*.voc *.aif *.aiff *.au *.raw)" ) ); #endif if( m_audioFile != "" )