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 0e6b8fb..ef0620e 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 30a499d..35b84ac 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,8 @@ Features Changelog --------- #### Version 0.4.0 (current sprint) -* Modulatioin wheel support -* Now using the [OBxd](https://obxd.wordpress.com) 4-pole lowpass filter implementation +* Modulation wheel support +* Now using the [Obxd](https://obxd.wordpress.com) 4-pole lowpass filter implementation Binary downloads ---------------- @@ -58,7 +58,7 @@ valid checksum for your DX7 keyboard. I'm in now way responsible if this breaks Credits & thanks ---------------- * DX Synth engine : Raph Levien and the [msfa](https://code.google.com/p/music-synthesizer-for-android) team -* LP Filter : Filatov Vadim (2DaT); taken from the excellent [OBxd](https://obxd.wordpress.com) project +* LP Filter : Filatov Vadim (2DaT); taken from the excellent [Obxd](https://obxd.wordpress.com) project * Original DX7 compilation : Jean-Marc Desprez (author of [SynprezFM](http://www.synprez.com/SynprezFM)) and to all the all crew who made these historic DX programs: Dave Benson, Frank Carvalho, Tim Conrardy, Jack Deckard, Chris Dodunski, Tim Garrett, Hitaye, Stephan Ibsen, Christian Jezreel, Narfman, Godric Wilkie * markusthegeek direct implication for this project @@ -66,7 +66,7 @@ TODO - Dexed ------------ * Implement a better DX look and feel (amp, pitch, algo) * Various code cleanup -* Standalone executable (for full support of the editor) +* Standalone executable (for full support of the sysex editor) TODO - msfa ----------- diff --git a/Source/PluginEditor.cpp b/Source/PluginEditor.cpp index ef1de51..50a3b7e 100644 --- a/Source/PluginEditor.cpp +++ b/Source/PluginEditor.cpp @@ -43,7 +43,7 @@ DexedAudioProcessorEditor::DexedAudioProcessorEditor (DexedAudioProcessor* owner cartridges.setTextWhenNothingSelected(String::empty); cartridges.setBounds(5, 5, 160, 18); cartridges.addItemList(processor->cartManager.cartNames, 1); - cartridges.setSelectedItemIndex(0); + cartridges.setSelectedItemIndex(0, NotificationType::dontSendNotification); cartridges.addListener(this); addAndMakeVisible (loadButton = new TextButton("LOAD")); @@ -132,7 +132,6 @@ void DexedAudioProcessorEditor::paint (Graphics& g) { } void DexedAudioProcessorEditor::buttonClicked(Button *buttonThatWasClicked) { - if (buttonThatWasClicked == loadButton) { FileChooser fc ("Import original DX sysex...", File::nonexistent, "*.syx;*.SYX;*.*", 1); diff --git a/Source/PluginFx.cpp b/Source/PluginFx.cpp index 65e140e..6acbf34 100644 --- a/Source/PluginFx.cpp +++ b/Source/PluginFx.cpp @@ -1,9 +1,9 @@ /** * * Copyright (c) 2013-2014 Pascal Gauthier. - * Copyright (C) 2013-2014 Filatov Vadim. + * Copyright (c) 2013-2014 Filatov Vadim. * - * Filter taken from the OBXd project : + * Filter taken from the Obxd project : * https://github.com/2DaT/Obxd * * This program is free software; you can redistribute it and/or diff --git a/Source/PluginFx.h b/Source/PluginFx.h index 125978b..b100601 100644 --- a/Source/PluginFx.h +++ b/Source/PluginFx.h @@ -30,13 +30,13 @@ class PluginFx { float rcor24,rcor24Inv; float bright; - //24 db multimode + // 24 db multimode float mm; float mmt; int mmch; inline float NR24(float sample,float g,float lpc); - // preprocess value from the UI + // preprocess values taken the UI float rCutoff; float rReso; diff --git a/Source/PluginProcessor.cpp b/Source/PluginProcessor.cpp index 7cfea6f..9060b61 100644 --- a/Source/PluginProcessor.cpp +++ b/Source/PluginProcessor.cpp @@ -88,6 +88,9 @@ void DexedAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBlock) workBlock = new SInt16[samplesPerBlock]; keyboardState.reset(); + + nextMidi= new MidiMessage(0xF0); + midiMsg = new MidiMessage(0xF0); } void DexedAudioProcessor::releaseResources() { @@ -130,24 +133,47 @@ void DexedAudioProcessor::processBlock(AudioSampleBuffer& buffer, MidiBuffer& mi // add messages to the buffer if the user is clicking on the on-screen keys keyboardState.processNextMidiBuffer (midiMessages, 0, numSamples, true); - // check input MidiBuffer::Iterator it(midiMessages); - MidiMessage msg; - int pos; - - while(it.getNextEvent(msg, pos)) { - processMidiMessage(&msg); - } - midiMessages.clear(); + hasMidiMessage = it.getNextEvent(*nextMidi,midiEventPos); - processSamples(numSamples, workBlock); float *channelData = buffer.getSampleData(0); - for(int i = 0; i < numSamples; i++ ) { - float f = ((float) workBlock[i]) / (float) 32768; - if( f > 1 ) f = 1; - if( f < -1 ) f = -1; - channelData[i] = (double) f; - } + int samplePos = 0; + + while(getNextEvent(&it, numSamples)) { + processMidiMessage(midiMsg); + } + + while ( samplePos < numSamples ) { + int block = 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)) { + processMidiMessage(midiMsg); + } + + if ( hasMidiMessage ) { + block = midiEventPos - samplePos; + } else { + block = numSamples - samplePos; + } + */ + + processSamples(block, workBlock); + for(int i = 0; i < block; i++ ) { + float f = ((float) workBlock[i+samplePos]) / (float) 32768; + if( f > 1 ) f = 1; + if( f < -1 ) f = -1; + channelData[i+samplePos] = (double) f; + } + + samplePos += block; + } fx.process(channelData, numSamples); @@ -162,7 +188,8 @@ void DexedAudioProcessor::processBlock(AudioSampleBuffer& buffer, MidiBuffer& mi for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i) { buffer.clear (i, 0, buffer.getNumSamples()); } - + + midiMessages.clear(); if ( ! midiOut.isEmpty() ) { midiMessages.swapWith(midiOut); } @@ -175,6 +202,15 @@ AudioProcessor* JUCE_CALLTYPE createPluginFilter() { return new DexedAudioProcessor(); } +bool DexedAudioProcessor::getNextEvent(MidiBuffer::Iterator* iter,const int samplePos) { + if (hasMidiMessage && midiEventPos <= samplePos) { + *midiMsg = *nextMidi; + hasMidiMessage = iter->getNextEvent(*nextMidi, midiEventPos); + return true; + } + return false; +} + void DexedAudioProcessor::processMidiMessage(MidiMessage *msg) { if ( msg->isSysEx() ) { diff --git a/Source/PluginProcessor.h b/Source/PluginProcessor.h index e88b930..013d92b 100644 --- a/Source/PluginProcessor.h +++ b/Source/PluginProcessor.h @@ -97,6 +97,12 @@ class DexedAudioProcessor : public AudioProcessor, public AsyncUpdater void initCtrl(); PropertiesFile::Options prefOptions; + + MidiMessage* nextMidi,*midiMsg; + bool hasMidiMessage; + int midiEventPos; + bool getNextEvent(MidiBuffer::Iterator* iter,const int samplePos); + public : StringArray programNames;