MediaBuffer* MidiEngine::readBuffer() { EAS_STATE state; EAS_State(mEasData, mEasHandle, &state); if ((state == EAS_STATE_STOPPED) || (state == EAS_STATE_ERROR)) { return NULL; } MediaBuffer *buffer; status_t err = mGroup->acquire_buffer(&buffer); if (err != OK) { ALOGE("readBuffer: no buffer"); return NULL; } EAS_I32 timeMs; EAS_GetLocation(mEasData, mEasHandle, &timeMs); int64_t timeUs = 1000ll * timeMs; buffer->meta_data()->setInt64(kKeyTime, timeUs); EAS_PCM* p = (EAS_PCM*) buffer->data(); int numBytesOutput = 0; for (int i = 0; i < NUM_COMBINE_BUFFERS; i++) { EAS_I32 numRendered; EAS_RESULT result = EAS_Render(mEasData, p, mEasConfig->mixBufferSize, &numRendered); if (result != EAS_SUCCESS) { ALOGE("EAS_Render returned %ld", result); break; } p += numRendered * mEasConfig->numChannels; numBytesOutput += numRendered * mEasConfig->numChannels * sizeof(EAS_PCM); } buffer->set_range(0, numBytesOutput); ALOGV("readBuffer: returning %zd in buffer %p", buffer->range_length(), buffer); return buffer; }
MIDI_RESULT MIDI_State(MIDI_HANDLE handle, MIDI_STATE *state) { EAS_RESULT result; // lock pthread_mutex_lock(&mutex); // check stream state if ((result = EAS_State(pEASData, handle, state)) != EAS_SUCCESS) { // unlock pthread_mutex_unlock(&mutex); return result; } // unlock pthread_mutex_unlock(&mutex); return MIDI_SUCCESS; }
int MidiFile::render() { EAS_RESULT result = EAS_FAILURE; EAS_I32 count; int temp; bool audioStarted = false; ALOGV("MidiFile::render"); // allocate render buffer mAudioBuffer = new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * NUM_BUFFERS]; if (!mAudioBuffer) { ALOGE("mAudioBuffer allocate failed"); goto threadExit; } // signal main thread that we started { Mutex::Autolock l(mMutex); mTid = gettid(); ALOGV("render thread(%d) signal", mTid); mCondition.signal(); } while (1) { mMutex.lock(); // nothing to render, wait for client thread to wake us up while (!mRender && !mExit) { ALOGV("MidiFile::render - signal wait"); mCondition.wait(mMutex); ALOGV("MidiFile::render - signal rx'd"); } if (mExit) { mMutex.unlock(); break; } // render midi data into the input buffer //ALOGV("MidiFile::render - rendering audio"); int num_output = 0; EAS_PCM* p = mAudioBuffer; for (int i = 0; i < NUM_BUFFERS; i++) { result = EAS_Render(mEasData, p, pLibConfig->mixBufferSize, &count); if (result != EAS_SUCCESS) { ALOGE("EAS_Render returned %ld", result); } p += count * pLibConfig->numChannels; num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM); } // update playback state and position // ALOGV("MidiFile::render - updating state"); EAS_GetLocation(mEasData, mEasHandle, &mPlayTime); EAS_State(mEasData, mEasHandle, &mState); mMutex.unlock(); // create audio output track if necessary if (!mAudioSink->ready()) { ALOGV("MidiFile::render - create output track"); if (createOutputTrack() != NO_ERROR) goto threadExit; } // Write data to the audio hardware // ALOGV("MidiFile::render - writing to audio output"); if ((temp = mAudioSink->write(mAudioBuffer, num_output)) < 0) { ALOGE("Error in writing:%d",temp); return temp; } // start audio output if necessary if (!audioStarted) { //ALOGV("MidiFile::render - starting audio"); mAudioSink->start(); audioStarted = true; } // still playing? if ((mState == EAS_STATE_STOPPED) || (mState == EAS_STATE_ERROR) || (mState == EAS_STATE_PAUSED)) { switch(mState) { case EAS_STATE_STOPPED: { ALOGV("MidiFile::render - stopped"); mPlayTime = mDuration; sendEvent(MEDIA_PLAYBACK_COMPLETE); break; } case EAS_STATE_ERROR: { ALOGE("MidiFile::render - error"); sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN); break; } case EAS_STATE_PAUSED: ALOGV("MidiFile::render - paused"); break; default: break; } mAudioSink->stop(); audioStarted = false; mRender = false; } } threadExit: mAudioSink.clear(); if (mAudioBuffer) { delete [] mAudioBuffer; mAudioBuffer = NULL; } mMutex.lock(); mTid = -1; mCondition.signal(); mMutex.unlock(); return result; }
static EAS_RESULT PlayFile (EAS_DATA_HANDLE easData, const char* filename, const char* outputFile, const S_EAS_LIB_CONFIG *pLibConfig, void *buffer, EAS_I32 bufferSize) { EAS_HANDLE handle; EAS_RESULT result, reportResult; EAS_I32 count; EAS_STATE state; EAS_I32 playTime; char waveFilename[256]; WAVE_FILE *wFile; EAS_INT i; EAS_PCM *p; EAS_FILE file; /* determine the name of the output file */ wFile = NULL; if (outputFile == NULL) { StrCopy(waveFilename, filename, sizeof(waveFilename)); if (!ChangeFileExt(waveFilename, "wav", sizeof(waveFilename))) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error in output filename %s\n", waveFilename); */ } return EAS_FAILURE; } outputFile = waveFilename; } /* call EAS library to open file */ file.path = filename; file.fd = 0; if ((reportResult = EAS_OpenFile(easData, &file, &handle)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_OpenFile returned %ld\n", reportResult); */ } return reportResult; } /* prepare to play the file */ if ((result = EAS_Prepare(easData, handle)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Prepare returned %ld\n", result); */ } reportResult = result; } /* get play length */ if ((result = EAS_ParseMetaData(easData, handle, &playTime)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_ParseMetaData returned %ld\n", result); */ } return result; } EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0xe624f4d9, 0x00000005 , playTime / 1000, playTime % 1000); if (reportResult == EAS_SUCCESS) { /* create the output file */ wFile = WaveFileCreate(outputFile, pLibConfig->numChannels, pLibConfig->sampleRate, sizeof(EAS_PCM) * 8); if (!wFile) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unable to create output file %s\n", waveFilename); */ } reportResult = EAS_FAILURE; } } /* rendering loop */ while (reportResult == EAS_SUCCESS) { /* we may render several buffers here to fill one host buffer */ for (i = 0, p = buffer; i < NUM_BUFFERS; i++, p+= pLibConfig->mixBufferSize * pLibConfig->numChannels) { /* get the current time */ if ((result = EAS_GetLocation(easData, handle, &playTime)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_GetLocation returned %d\n",result); */ } if (reportResult == EAS_SUCCESS) reportResult = result; break; } { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Parser time: %d.%03d\n", playTime / 1000, playTime % 1000); */ } /* render a buffer of audio */ if ((result = EAS_Render(easData, p, pLibConfig->mixBufferSize, &count)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Render returned %d\n",result); */ } if (reportResult == EAS_SUCCESS) reportResult = result; } } if (result == EAS_SUCCESS) { /* write it to the wave file */ if (WaveFileWrite(wFile, buffer, bufferSize) != bufferSize) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "WaveFileWrite failed\n"); */ } reportResult = EAS_FAILURE; } } if (reportResult == EAS_SUCCESS) { /* check stream state */ if ((result = EAS_State(easData, handle, &state)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_State returned %d\n", result); */ } reportResult = result; } /* is playback complete */ if ((state == EAS_STATE_STOPPED) || (state == EAS_STATE_ERROR)) break; } } /* close the output file */ if (wFile) { if (!WaveFileClose(wFile)) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error closing wave file %s\n", waveFilename); */ } if (reportResult == EAS_SUCCESS) result = EAS_FAILURE; } } /* close the input file */ if ((result = EAS_CloseFile(easData,handle)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Close returned %ld\n", result); */ } if (reportResult == EAS_SUCCESS) result = EAS_FAILURE; } return reportResult; } /* end PlayFile */