diff --git a/Builds/MacOSX/Dexed.xcodeproj/project.xcworkspace/xcuserdata/asb2m10.xcuserdatad/UserInterfaceState.xcuserstate b/Builds/MacOSX/Dexed.xcodeproj/project.xcworkspace/xcuserdata/asb2m10.xcuserdatad/UserInterfaceState.xcuserstate index 750d638..7d4ab43 100644 Binary files a/Builds/MacOSX/Dexed.xcodeproj/project.xcworkspace/xcuserdata/asb2m10.xcuserdatad/UserInterfaceState.xcuserstate and b/Builds/MacOSX/Dexed.xcodeproj/project.xcworkspace/xcuserdata/asb2m10.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/README.md b/README.md index ebe6d29..f8352f1 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,10 @@ Dexed is a multi platform, multi format plugin synth that is closely modeled on Under the hood it uses [music-synthesizer-for-android](https://code.google.com/p/music-synthesizer-for-android) for the synth engine and [JUCE](http://wwww.juce.com) as a plugin wrapper. -The goal of this project is to be a great tool/companion for the original DX7. Sound engine +The goal of this project is to be a tool/companion for the original DX7. Sound engine with 'float' value parameters, different waveform à la TX81z would be great but anything that goes beyond the DX7 should and will be a fork of this project. This is to keep the compatiblity with -the original DX7. +the original machine. Dexed is licensed on the GPL v2. The msfa component (acronym for music synthesizer for android, see msfa in the source folder) stays on the Apache 2.0 license to able to collaborate between projects. @@ -24,6 +24,10 @@ Features Changelog --------- +#### Version 0.5.0 +* Linux support +* Fix large DAW blocksize with midi events + #### Version 0.4.0 * Modulation wheel support * Now using the [Obxd](https://obxd.wordpress.com) 4-pole lowpass filter implementation @@ -35,6 +39,7 @@ Binary downloads Dexed is not a finished product but it is stable enough to be used in a DAW environment: in normal operation it shouldn't crash and the VST state saving works. +* Version 0.5.0 [vst win32](http://le-son666.com/software/dexed/dexed-0.5.0-win32.zip) - [vst win64](http://le-son666.com/software/dexed/dexed-0.5.0-win64.zip) - [vst os x](http://le-son666.com/software/dexed/dexed-0.5.0-osx.vst.zip) * Version 0.4.0 [vst win32](http://le-son666.com/software/dexed/dexed-0.4.0-win32.zip) - [vst win64](http://le-son666.com/software/dexed/dexed-0.4.0-win64.zip) - [vst os x](http://le-son666.com/software/dexed/dexed-0.4.0-osx.vst.zip) * Version 0.3.0 [vst win32](http://le-son666.com/software/dexed/dexed-0.3.0-win32.zip) - [vst win64](http://le-son666.com/software/dexed/dexed-0.3.0-win64.zip) - [vst os x](http://le-son666.com/software/dexed/dexed-0.3.0-osx.vst.zip) @@ -77,7 +82,6 @@ TODO - Dexed * Implement a better DX look and feel (amp, pitch, algo) * Various code cleanup * Standalone executable (for full support of the sysex editor) -* Midi sample resolution on DAW block size TODO - msfa ----------- diff --git a/Source/PluginProcessor.cpp b/Source/PluginProcessor.cpp index 4cef115..69e6dae 100644 --- a/Source/PluginProcessor.cpp +++ b/Source/PluginProcessor.cpp @@ -46,7 +46,6 @@ DexedAudioProcessor::DexedAudioProcessor() { lastStateSave = 0; currentNote = -1; - workBlock = NULL; vuSignal = 0; initCtrl(); setCurrentProgram(0); @@ -90,9 +89,6 @@ void DexedAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBlock) sustain = false; extra_buf_size = 0; - workBlockSize = samplesPerBlock; - workBlock = new float[samplesPerBlock]; - keyboardState.reset(); nextMidi = new MidiMessage(0xF0); @@ -109,10 +105,6 @@ void DexedAudioProcessor::releaseResources() { voices[note].live = false; } - if ( workBlock != NULL ) { - delete workBlock; - } - keyboardState.reset(); delete nextMidi; @@ -121,6 +113,7 @@ void DexedAudioProcessor::releaseResources() { void DexedAudioProcessor::processBlock(AudioSampleBuffer& buffer, MidiBuffer& midiMessages) { int numSamples = buffer.getNumSamples(); + int i = 0; if ( refreshVoice ) { for(int i=0;i workBlockSize ) { - delete workBlock; - workBlockSize = numSamples; - workBlock = new float[workBlockSize]; - } - // Now pass any incoming midi messages to our keyboard state object, and let it // add messages to the buffer if the user is clicking on the on-screen keys keyboardState.processNextMidiBuffer (midiMessages, 0, numSamples, true); @@ -146,38 +132,67 @@ void DexedAudioProcessor::processBlock(AudioSampleBuffer& buffer, MidiBuffer& mi hasMidiMessage = it.getNextEvent(*nextMidi,midiEventPos); float *channelData = buffer.getSampleData(0); - int samplePos = 0; - - while(getNextEvent(&it, numSamples)) { - processMidiMessage(midiMsg); + + // flush first events + for (i = 0; i < numSamples && i < extra_buf_size; i++) { + channelData[i] = extra_buf[i]; } - while ( samplePos < numSamples ) { - int block = numSamples; + // remaining buffer is still to be processed + if (extra_buf_size > numSamples) { + for (int j = 0; j < extra_buf_size - numSamples; j++) { + extra_buf[j] = extra_buf[j + numSamples]; + } + extra_buf_size -= numSamples; - /* - * MIDI message needs to be bound to - * the sample. When a rendering occurs - * very large blocks can be passed and - * without this code, the plugin will be - * out of sync... TODO! - - while(getNextEvent(&it, samplePos)) { + // flush the event, they will be process in next cycle + while(getNextEvent(&it, numSamples)) { processMidiMessage(midiMsg); } - - if ( hasMidiMessage ) { - block = midiEventPos - samplePos; - } else { - block = numSamples - samplePos; + } else { + for (; i < numSamples; i += N) { + AlignedBuf audiobuf; + float sumbuf[N]; + + while(getNextEvent(&it, i)) { + processMidiMessage(midiMsg); + } + + for (int j = 0; j < N; ++j) { + audiobuf.get()[j] = 0; + sumbuf[j] = 0; + } + int32_t lfovalue = lfo.getsample(); + int32_t lfodelay = lfo.getdelay(); + for (int note = 0; note < MAX_ACTIVE_NOTES; ++note) { + if (voices[note].live) { + voices[note].dx7_note->compute(audiobuf.get(), lfovalue, lfodelay, &controllers); + + for (int j=0; j < N; ++j) { + int32_t val = audiobuf.get()[j] >> 4; + int clip_val = val < -(1 << 24) ? 0x8000 : val >= (1 << 24) ? 0x7fff : val >> 9; + float f = ((float) clip_val) / (float) 32768; + if( f > 1 ) f = 1; + if( f < -1 ) f = -1; + sumbuf[j] += f; + audiobuf.get()[j] = 0; + } + } + } + + int jmax = numSamples - i; + for (int j = 0; j < N; ++j) { + if (j < jmax) { + channelData[i + j] = sumbuf[j]; + } else { + extra_buf[j - jmax] = sumbuf[j]; + } + } } - */ - - processSamples(block, workBlock); - for(int i = 0; i < block; i++ ) - channelData[i+samplePos] = workBlock[i]; - - samplePos += block; + } + + while(getNextEvent(&it, numSamples)) { + processMidiMessage(midiMsg); } fx.process(channelData, numSamples); @@ -211,6 +226,14 @@ void DexedAudioProcessor::processBlock(AudioSampleBuffer& buffer, MidiBuffer& mi } } +void DexedAudioProcessor::processSamples(int n_samples, float *buffer) { + int i; + + + + extra_buf_size = i - n_samples; +} + //============================================================================== // This creates new instances of the plugin.. @@ -359,59 +382,6 @@ void DexedAudioProcessor::keyup(uint8_t pitch) { } } - -void DexedAudioProcessor::processSamples(int n_samples, float *buffer) { - int i; - for (i = 0; i < n_samples && i < extra_buf_size; i++) { - buffer[i] = extra_buf[i]; - } - if (extra_buf_size > n_samples) { - for (int j = 0; j < extra_buf_size - n_samples; j++) { - extra_buf[j] = extra_buf[j + n_samples]; - } - extra_buf_size -= n_samples; - return; - } - - for (; i < n_samples; i += N) { - AlignedBuf audiobuf; - float sumbuf[N]; - - for (int j = 0; j < N; ++j) { - audiobuf.get()[j] = 0; - sumbuf[j] = 0; - } - int32_t lfovalue = lfo.getsample(); - int32_t lfodelay = lfo.getdelay(); - for (int note = 0; note < MAX_ACTIVE_NOTES; ++note) { - if (voices[note].live) { - voices[note].dx7_note->compute(audiobuf.get(), lfovalue, lfodelay, &controllers); - - for (int j=0; j < N; ++j) { - int32_t val = audiobuf.get()[j] >> 4; - int clip_val = val < -(1 << 24) ? 0x8000 : val >= (1 << 24) ? 0x7fff : val >> 9; - float f = ((float) clip_val) / (float) 32768; - if( f > 1 ) f = 1; - if( f < -1 ) f = -1; - sumbuf[j] += f; - audiobuf.get()[j] = 0; - } - } - } - - int jmax = n_samples - i; - for (int j = 0; j < N; ++j) { - if (j < jmax) { - buffer[i + j] = sumbuf[j]; - } else { - extra_buf[j - jmax] = sumbuf[j]; - } - } - } - extra_buf_size = i - n_samples; -} - - // ==================================================================== bool DexedAudioProcessor::peekVoiceStatus() { if ( currentNote == -1 ) diff --git a/Source/PluginProcessor.h b/Source/PluginProcessor.h index f26e7ef..4613d9f 100644 --- a/Source/PluginProcessor.h +++ b/Source/PluginProcessor.h @@ -57,8 +57,6 @@ class DexedAudioProcessor : public AudioProcessor, public AsyncUpdater float extra_buf[N]; int extra_buf_size; - float *workBlock; - int workBlockSize; int currentProgram; /**