Closed ygtorres closed 3 years ago
Hi, sorry for my poor English.
I had an issue. The stream became disconnected when I was plugging or unplugging headphones. So I modified midi.cpp code a little bit to fix this.
//////////////////////////////////////////////////////////////////////////////// // // MidiDriver - An Android Midi Driver. // // Copyright (C) 2013 Bill Farmer // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Bill Farmer william j farmer [at] yahoo [dot] co [dot] uk. // /////////////////////////////////////////////////////////////////////////////// #include <jni.h> #include <assert.h> #include <pthread.h> // for oboe native audio #include <oboe/Oboe.h> // for EAS midi #include "eas.h" #include "eas_reverb.h" #include "midi.h" // determines how many EAS buffers to fill a host buffer #define NUM_BUFFERS 4 // mutex pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // oboe stream std::shared_ptr<oboe::AudioStream> oboeStream; // EAS data EAS_DATA_HANDLE pEASData; const S_EAS_LIB_CONFIG *pLibConfig; static EAS_I32 bufferSize; EAS_HANDLE midiHandle; jboolean oboe_init(); // oboe callback class OboeCallback : public oboe::AudioStreamCallback { public: oboe::DataCallbackResult onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames) { EAS_RESULT result; EAS_I32 numGenerated; EAS_I32 count = 0; // We requested AudioFormat::I16. So if the stream opens // we know we got the I16 format. auto *outputData = static_cast<int16_t *>(audioData); while (count < bufferSize) { // lock pthread_mutex_lock(&mutex); result = EAS_Render(pEASData, outputData + count, pLibConfig->mixBufferSize, &numGenerated); // unlock pthread_mutex_unlock(&mutex); assert(result == EAS_SUCCESS); count += numGenerated * pLibConfig->numChannels; } return oboe::DataCallbackResult::Continue; } void onErrorAfterClose(oboe::AudioStream* audioStream , oboe::Result error ) override { if(error == oboe::Result::ErrorDisconnected){ oboe_init(); } } }; // oboe callback OboeCallback oboeCallback; // build oboe oboe::Result buildOboe() { oboe::AudioStreamBuilder builder; builder.setDirection(oboe::Direction::Output); builder.setPerformanceMode(oboe::PerformanceMode::LowLatency); builder.setSharingMode(oboe::SharingMode::Exclusive); builder.setFormat(oboe::AudioFormat::I16); builder.setFramesPerCallback(bufferSize / pLibConfig->numChannels); builder.setChannelCount(pLibConfig->numChannels); builder.setSampleRate(pLibConfig->sampleRate); builder.setCallback(&oboeCallback); return builder.openStream(oboeStream); } // close oboe oboe::Result closeOboe() { oboeStream->requestStop(); return oboeStream->close(); } // init EAS midi EAS_RESULT initEAS() { EAS_RESULT result; // get the library configuration pLibConfig = EAS_Config(); if (pLibConfig == NULL || pLibConfig->libVersion != LIB_VERSION) return EAS_FAILURE; // calculate buffer size bufferSize = pLibConfig->mixBufferSize * pLibConfig->numChannels * NUM_BUFFERS; // init library if ((result = EAS_Init(&pEASData)) != EAS_SUCCESS) return result; // select reverb preset and enable EAS_SetParameter(pEASData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_PRESET, EAS_PARAM_REVERB_CHAMBER); EAS_SetParameter(pEASData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_BYPASS, EAS_FALSE); // open midi stream if ((result = EAS_OpenMIDIStream(pEASData, &midiHandle, NULL)) != EAS_SUCCESS) return result; return EAS_SUCCESS; } // shutdown EAS midi void shutdownEAS() { if (midiHandle != NULL) { EAS_CloseMIDIStream(pEASData, midiHandle); midiHandle = NULL; } if (pEASData != NULL) { EAS_Shutdown(pEASData); pEASData = NULL; } } // init mididriver jboolean midi_init() { EAS_RESULT result; if ((result = initEAS()) != EAS_SUCCESS) { shutdownEAS(); LOG_E(LOG_TAG, "Init EAS failed: %ld", result); return JNI_FALSE; } return oboe_init(); } jboolean oboe_init(){ oboe::Result oboeResult; // LOG_D(LOG_TAG, "Init EAS success, buffer: %ld", bufferSize); if ((oboeResult = buildOboe()) != oboe::Result::OK) { shutdownEAS(); LOG_E(LOG_TAG, "Failed to create oboe stream. Error: %s", oboe::convertToText(oboeResult)); return JNI_FALSE; } if ((oboeResult = oboeStream->requestStart()) != oboe::Result::OK) { shutdownEAS(); closeOboe(); LOG_E(LOG_TAG, "Failed to start oboe stream. Error: %s", oboe::convertToText(oboeResult)); return JNI_FALSE; } return JNI_TRUE; } // midi write jboolean midi_write(EAS_U8 *bytes, jint length) { EAS_RESULT result; if (pEASData == NULL || midiHandle == NULL) return JNI_FALSE; // lock pthread_mutex_lock(&mutex); result = EAS_WriteMIDIStream(pEASData, midiHandle, bytes, length); // unlock pthread_mutex_unlock(&mutex); if (result != EAS_SUCCESS) return JNI_FALSE; return JNI_TRUE; } // set EAS master volume jboolean midi_setVolume(jint volume) { EAS_RESULT result; if (pEASData == NULL || midiHandle == NULL) return JNI_FALSE; result = EAS_SetVolume(pEASData, NULL, (EAS_I32) volume); if (result != EAS_SUCCESS) return JNI_FALSE; return JNI_TRUE; } // Set EAS reverb jboolean midi_setReverb(jint preset) { EAS_RESULT result; if (preset >= 0) { result = EAS_SetParameter(pEASData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_PRESET, preset); if (result != EAS_SUCCESS) { LOG_E(LOG_TAG, "Set EAS reverb preset failed: %ld", result); return JNI_FALSE; } result = EAS_SetParameter(pEASData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_BYPASS, EAS_FALSE); if (result != EAS_SUCCESS) { LOG_E(LOG_TAG, "Enable EAS reverb failed: %ld", result); return JNI_FALSE; } } else { result = EAS_SetParameter(pEASData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_BYPASS, EAS_TRUE); if (result != EAS_SUCCESS) { LOG_E(LOG_TAG, "Disable EAS reverb failed: %ld", result); return JNI_FALSE; } } return JNI_TRUE; } // shutdown EAS midi jboolean midi_shutdown() { closeOboe(); shutdownEAS(); return JNI_TRUE; }
Thank you, I edited your comment to make it easier to read. OK, that works, it will be in the next version.
Ok you're welcome.
Hi, sorry for my poor English.
I had an issue. The stream became disconnected when I was plugging or unplugging headphones. So I modified midi.cpp code a little bit to fix this.