diff --git a/Source/PluginProcessor.cpp b/Source/PluginProcessor.cpp index 83a8978..bc612d1 100644 --- a/Source/PluginProcessor.cpp +++ b/Source/PluginProcessor.cpp @@ -8,147 +8,197 @@ #include "PluginProcessor.h" #include "PluginEditor.h" - -#include +#include "BinaryData.h" //============================================================================== CustomDrumsAudioProcessor::CustomDrumsAudioProcessor() : AudioProcessor(BusesProperties() .withOutput("Output", juce::AudioChannelSet::stereo(), true) - ) -{ + ) { + + formatManager.registerBasicFormats(); + wavFormat = formatManager.findFormatForFileExtension("wav"); } -CustomDrumsAudioProcessor::~CustomDrumsAudioProcessor() -{ +CustomDrumsAudioProcessor::~CustomDrumsAudioProcessor() { + +} + +void CustomDrumsAudioProcessor::loadFiles() { + const static std::vector files = { + "bass_wav", + "crash_wav", + "floortom_wav", + "hihat_wav", + "hihatfoot_wav", + "hihatopen_wav", + "ride_wav", + "sharedrum_wav", + "sharestick_wav", + "tom1_wav", + "tom2_wav", + "clap_wav" + }; + + for (auto file : files) { + int dataSize; + const char* audioData = BinaryData::getNamedResource(file.c_str(), dataSize); + juce::MemoryInputStream input{ audioData, static_cast(dataSize), false }; + loadFile(&input); + } + +} + +void CustomDrumsAudioProcessor::loadFile(juce::MemoryInputStream* input) { + int fileIndex = fileBuffers.size(); + auto* reader = wavFormat->createReaderFor(input, false); + if (reader != nullptr) { + fileBuffers.push_back({}); + fileBuffers[fileIndex].setSize((int)reader->numChannels, (int)reader->lengthInSamples); // [4] + reader->read(&fileBuffers[fileIndex], // [5] + 0, // [5.1] + (int)reader->lengthInSamples, // [5.2] + 0, // [5.3] + true, // [5.4] + true); // [5.5] + } + } //============================================================================== -const juce::String CustomDrumsAudioProcessor::getName() const -{ +const juce::String CustomDrumsAudioProcessor::getName() const { return JucePlugin_Name; } -bool CustomDrumsAudioProcessor::acceptsMidi() const -{ +bool CustomDrumsAudioProcessor::acceptsMidi() const { return true; } -bool CustomDrumsAudioProcessor::producesMidi() const -{ +bool CustomDrumsAudioProcessor::producesMidi() const { return true; } -bool CustomDrumsAudioProcessor::isMidiEffect() const -{ - return true; +bool CustomDrumsAudioProcessor::isMidiEffect() const { + return false; } -double CustomDrumsAudioProcessor::getTailLengthSeconds() const -{ +double CustomDrumsAudioProcessor::getTailLengthSeconds() const { return 0.0; } -int CustomDrumsAudioProcessor::getNumPrograms() -{ +int CustomDrumsAudioProcessor::getNumPrograms() { return 1; // NB: some hosts don't cope very well if you tell them there are 0 programs, - // so this should be at least 1, even if you're not really implementing programs. + // so this should be at least 1, even if you're not really implementing programs. } -int CustomDrumsAudioProcessor::getCurrentProgram() -{ +int CustomDrumsAudioProcessor::getCurrentProgram() { return 0; } -void CustomDrumsAudioProcessor::setCurrentProgram(int index) -{ +void CustomDrumsAudioProcessor::setCurrentProgram(int index) { } -const juce::String CustomDrumsAudioProcessor::getProgramName(int index) -{ +const juce::String CustomDrumsAudioProcessor::getProgramName(int index) { return {}; } -void CustomDrumsAudioProcessor::changeProgramName(int index, const juce::String& newName) -{ +void CustomDrumsAudioProcessor::changeProgramName(int index, const juce::String& newName) { } //============================================================================== -void CustomDrumsAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBlock) -{ +void CustomDrumsAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBlock) { // Use this method as the place to do any pre-playback // initialisation that you need.. + loadFiles(); } -void CustomDrumsAudioProcessor::releaseResources() -{ +void CustomDrumsAudioProcessor::releaseResources() { // When playback stops, you can use this as an opportunity to free up any // spare memory, etc. + fileBuffers.clear(); + fileQueue.clear(); } -bool CustomDrumsAudioProcessor::isBusesLayoutSupported(const BusesLayout& layouts) const -{ +bool CustomDrumsAudioProcessor::isBusesLayoutSupported(const BusesLayout& layouts) const { juce::ignoreUnused(layouts); return true; } -void CustomDrumsAudioProcessor::processBlock(juce::AudioBuffer& buffer, juce::MidiBuffer& midiMessages) -{ +void CustomDrumsAudioProcessor::processBlock(juce::AudioBuffer& buffer, juce::MidiBuffer& midiMessages) { juce::ScopedNoDenormals noDenormals; auto totalNumInputChannels = getTotalNumInputChannels(); auto totalNumOutputChannels = getTotalNumOutputChannels(); - buffer.clear(); - juce::MidiBuffer processedMidi; - for (const auto metadata : midiMessages) - { + for (const auto metadata : midiMessages) { auto message = metadata.getMessage(); const auto time = metadata.samplePosition; - if (message.isNoteOn()) - { - - const int firstNote = 24; - std::cout << "Processed Input ! " << message.getChannel() << " " << abs(message.getNoteNumber() - 24) << std::endl; + if (message.isNoteOn()) { + + FilePlay play; + play.position = 0; + play.fileIndex = message.getNoteNumber() % 12; + play.volume = message.getFloatVelocity() * message.getFloatVelocity(); + fileQueue.push_back(play); } processedMidi.addEvent(message, time); } + playSamples(buffer); + midiMessages.swapWith(processedMidi); } //============================================================================== -bool CustomDrumsAudioProcessor::hasEditor() const -{ +bool CustomDrumsAudioProcessor::hasEditor() const { return true; // (change this to false if you choose to not supply an editor) } -juce::AudioProcessorEditor* CustomDrumsAudioProcessor::createEditor() -{ +juce::AudioProcessorEditor* CustomDrumsAudioProcessor::createEditor() { return new CustomDrumsAudioProcessorEditor(*this); } +void CustomDrumsAudioProcessor::playSamples(juce::AudioBuffer& buffer) { + int numberOfSamples = buffer.getNumSamples(); + buffer.clear(); + for (int i = 0; i < numberOfSamples; i++) { + for (int j = 0; j < fileQueue.size(); j++) { + FilePlay& file = fileQueue[j]; + int& position = file.position; + auto& fileBuffer = fileBuffers[file.fileIndex]; + float volume = file.volume; + + if (position >= fileBuffer.getNumSamples()) { + fileQueue.erase(fileQueue.begin() + j); + continue; + } + + buffer.addSample(0, i, fileBuffer.getSample(0, position) * volume); + buffer.addSample(1, i, fileBuffer.getSample(1, position) * volume); + + position++; + } + } +} + //============================================================================== -void CustomDrumsAudioProcessor::getStateInformation(juce::MemoryBlock& destData) -{ +void CustomDrumsAudioProcessor::getStateInformation(juce::MemoryBlock& destData) { // You should use this method to store your parameters in the memory block. // You could do that either as raw data, or use the XML or ValueTree classes // as intermediaries to make it easy to save and load complex data. } -void CustomDrumsAudioProcessor::setStateInformation(const void* data, int sizeInBytes) -{ +void CustomDrumsAudioProcessor::setStateInformation(const void* data, int sizeInBytes) { // You should use this method to restore your parameters from this memory block, // whose contents will have been created by the getStateInformation() call. } //============================================================================== // This creates new instances of the plugin.. -juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter() -{ +juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter() { return new CustomDrumsAudioProcessor(); } diff --git a/Source/PluginProcessor.h b/Source/PluginProcessor.h index 7c4f73c..f236a2e 100644 --- a/Source/PluginProcessor.h +++ b/Source/PluginProcessor.h @@ -10,48 +10,62 @@ #include +struct FilePlay { + int position; + int fileIndex; + float volume; +}; + //============================================================================== /** */ -class CustomDrumsAudioProcessor : public juce::AudioProcessor -{ +class CustomDrumsAudioProcessor : public juce::AudioProcessor { public: - //============================================================================== - CustomDrumsAudioProcessor(); - ~CustomDrumsAudioProcessor() override; + //============================================================================== + CustomDrumsAudioProcessor(); + ~CustomDrumsAudioProcessor() override; - //============================================================================== - void prepareToPlay (double sampleRate, int samplesPerBlock) override; - void releaseResources() override; + //============================================================================== + void prepareToPlay(double sampleRate, int samplesPerBlock) override; + void loadFile(juce::MemoryInputStream* input); + void loadFiles(); + void releaseResources() override; - bool isBusesLayoutSupported (const BusesLayout& layouts) const override; + bool isBusesLayoutSupported(const BusesLayout& layouts) const override; - void processBlock (juce::AudioBuffer&, juce::MidiBuffer&) override; + void processBlock(juce::AudioBuffer&, juce::MidiBuffer&) override; - //============================================================================== - juce::AudioProcessorEditor* createEditor() override; - bool hasEditor() const override; + //============================================================================== + juce::AudioProcessorEditor* createEditor() override; + bool hasEditor() const override; - //============================================================================== - const juce::String getName() const override; + //============================================================================== + const juce::String getName() const override; - bool acceptsMidi() const override; - bool producesMidi() const override; - bool isMidiEffect() const override; - double getTailLengthSeconds() const override; + bool acceptsMidi() const override; + bool producesMidi() const override; + bool isMidiEffect() const override; + double getTailLengthSeconds() const override; - //============================================================================== - int getNumPrograms() override; - int getCurrentProgram() override; - void setCurrentProgram (int index) override; - const juce::String getProgramName (int index) override; - void changeProgramName (int index, const juce::String& newName) override; + //============================================================================== + int getNumPrograms() override; + int getCurrentProgram() override; + void setCurrentProgram(int index) override; + const juce::String getProgramName(int index) override; + void changeProgramName(int index, const juce::String& newName) override; - //============================================================================== - void getStateInformation (juce::MemoryBlock& destData) override; - void setStateInformation (const void* data, int sizeInBytes) override; + //============================================================================== + void getStateInformation(juce::MemoryBlock& destData) override; + void setStateInformation(const void* data, int sizeInBytes) override; private: - //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CustomDrumsAudioProcessor) + juce::AudioFormatManager formatManager; + juce::AudioFormat* wavFormat; + std::vector fileQueue; + std::vector fileBuffers; + + void playSamples(juce::AudioBuffer& buffer); + + //============================================================================== + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CustomDrumsAudioProcessor) };