1faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen/* 2faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen * Copyright (C) 2014 The Android Open Source Project 3faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen * 4faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen * Licensed under the Apache License, Version 2.0 (the "License"); 5faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen * you may not use this file except in compliance with the License. 6faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen * You may obtain a copy of the License at 7faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen * 8faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen * http://www.apache.org/licenses/LICENSE-2.0 9faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen * 10faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen * Unless required by applicable law or agreed to in writing, software 11faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen * distributed under the License is distributed on an "AS IS" BASIS, 12faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen * See the License for the specific language governing permissions and 14faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen * limitations under the License. 15faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen */ 16faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 17faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen//#define LOG_NDEBUG 0 18faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen#define LOG_TAG "MidiExtractor" 19faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen#include <utils/Log.h> 20faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 21faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen#include "include/MidiExtractor.h" 22faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 23faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen#include <media/MidiIoWrapper.h> 24faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen#include <media/stagefright/foundation/ADebug.h> 25faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen#include <media/stagefright/MediaBufferGroup.h> 26faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen#include <media/stagefright/MediaDefs.h> 27faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen#include <media/stagefright/MetaData.h> 28faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen#include <media/stagefright/MediaSource.h> 29faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen#include <libsonivox/eas_reverb.h> 30faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 31faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissennamespace android { 32faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 33faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen// how many Sonivox output buffers to aggregate into one MediaBuffer 34faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissenstatic const int NUM_COMBINE_BUFFERS = 4; 35faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 36faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissenclass MidiSource : public MediaSource { 37faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 38faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissenpublic: 39faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen MidiSource( 40faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen const sp<MidiEngine> &engine, 41faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen const sp<MetaData> &trackMetadata); 42faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 43faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen virtual status_t start(MetaData *params); 44faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen virtual status_t stop(); 45faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen virtual sp<MetaData> getFormat(); 46faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 47faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen virtual status_t read( 48faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen MediaBuffer **buffer, const ReadOptions *options = NULL); 49faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 50faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissenprotected: 51faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen virtual ~MidiSource(); 52faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 53faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissenprivate: 54faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen sp<MidiEngine> mEngine; 55faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen sp<MetaData> mTrackMetadata; 56faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen bool mInitCheck; 57faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen bool mStarted; 58faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 59faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen status_t init(); 60faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 61faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen // no copy constructor or assignment 62faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen MidiSource(const MidiSource &); 63faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen MidiSource &operator=(const MidiSource &); 64faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 65faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen}; 66faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 67faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 68faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen// Midisource 69faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 70faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco NelissenMidiSource::MidiSource( 71faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen const sp<MidiEngine> &engine, 72faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen const sp<MetaData> &trackMetadata) 73faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen : mEngine(engine), 74faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mTrackMetadata(trackMetadata), 75faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mInitCheck(false), 76faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mStarted(false) 77faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen{ 78faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen ALOGV("MidiSource ctor"); 79faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mInitCheck = init(); 80faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} 81faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 82faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco NelissenMidiSource::~MidiSource() 83faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen{ 84faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen ALOGV("MidiSource dtor"); 85faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen if (mStarted) { 86faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen stop(); 87faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen } 88faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} 89faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 90faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissenstatus_t MidiSource::start(MetaData * /* params */) 91faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen{ 92faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen ALOGV("MidiSource::start"); 93faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 94faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen CHECK(!mStarted); 95faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mStarted = true; 96faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mEngine->allocateBuffers(); 97faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen return OK; 98faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} 99faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 100faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissenstatus_t MidiSource::stop() 101faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen{ 102faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen ALOGV("MidiSource::stop"); 103faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 104faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen CHECK(mStarted); 105faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mStarted = false; 106faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mEngine->releaseBuffers(); 107faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 108faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen return OK; 109faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} 110faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 111faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissensp<MetaData> MidiSource::getFormat() 112faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen{ 113faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen return mTrackMetadata; 114faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} 115faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 116faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissenstatus_t MidiSource::read( 117faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen MediaBuffer **outBuffer, const ReadOptions *options) 118faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen{ 119faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen ALOGV("MidiSource::read"); 120faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen MediaBuffer *buffer; 121faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen // process an optional seek request 122faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen int64_t seekTimeUs; 123faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen ReadOptions::SeekMode mode; 124faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen if ((NULL != options) && options->getSeekTo(&seekTimeUs, &mode)) { 125faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen if (seekTimeUs <= 0LL) { 126faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen seekTimeUs = 0LL; 127faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen } 128faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mEngine->seekTo(seekTimeUs); 129faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen } 130faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen buffer = mEngine->readBuffer(); 131faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen *outBuffer = buffer; 132faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen ALOGV("MidiSource::read %p done", this); 133faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen return buffer != NULL ? (status_t) OK : (status_t) ERROR_END_OF_STREAM; 134faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} 135faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 136faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissenstatus_t MidiSource::init() 137faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen{ 138faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen ALOGV("MidiSource::init"); 139faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen return OK; 140faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} 141faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 142faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen// MidiEngine 143faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 144faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco NelissenMidiEngine::MidiEngine(const sp<DataSource> &dataSource, 145faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen const sp<MetaData> &fileMetadata, 146faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen const sp<MetaData> &trackMetadata) : 147faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mGroup(NULL), 148faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mEasData(NULL), 149faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mEasHandle(NULL), 150faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mEasConfig(NULL), 151faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mIsInitialized(false) { 152faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mIoWrapper = new MidiIoWrapper(dataSource); 153faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen // spin up a new EAS engine 154faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen EAS_I32 temp; 155faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen EAS_RESULT result = EAS_Init(&mEasData); 156faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 157faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen if (result == EAS_SUCCESS) { 158faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen result = EAS_OpenFile(mEasData, mIoWrapper->getLocator(), &mEasHandle); 159faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen } 160faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen if (result == EAS_SUCCESS) { 161faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen result = EAS_Prepare(mEasData, mEasHandle); 162faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen } 163faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen if (result == EAS_SUCCESS) { 164faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen result = EAS_ParseMetaData(mEasData, mEasHandle, &temp); 165faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen } 166faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 167faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen if (result != EAS_SUCCESS) { 168faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen return; 169faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen } 170faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 171faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen if (fileMetadata != NULL) { 172faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen fileMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MIDI); 173faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen } 174faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 175faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen if (trackMetadata != NULL) { 176faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen trackMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); 177faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen trackMetadata->setInt64(kKeyDuration, 1000ll * temp); // milli->micro 178faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mEasConfig = EAS_Config(); 179faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen trackMetadata->setInt32(kKeySampleRate, mEasConfig->sampleRate); 180faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen trackMetadata->setInt32(kKeyChannelCount, mEasConfig->numChannels); 18178bd91b15ee8ea5aa2ab5a8cad7e892cb2d01c1bLajos Molnar trackMetadata->setInt32(kKeyPcmEncoding, kAudioEncodingPcm16bit); 182faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen } 183faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mIsInitialized = true; 184faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} 185faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 186faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco NelissenMidiEngine::~MidiEngine() { 187faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen if (mEasHandle) { 188faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen EAS_CloseFile(mEasData, mEasHandle); 189faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen } 190faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen if (mEasData) { 191faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen EAS_Shutdown(mEasData); 192faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen } 193faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen delete mGroup; 194faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 195faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} 196faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 197faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissenstatus_t MidiEngine::initCheck() { 198faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen return mIsInitialized ? OK : UNKNOWN_ERROR; 199faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} 200faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 201faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissenstatus_t MidiEngine::allocateBuffers() { 202faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen // select reverb preset and enable 203faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_PRESET, EAS_PARAM_REVERB_CHAMBER); 204faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_BYPASS, EAS_FALSE); 205faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 206faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mGroup = new MediaBufferGroup; 207faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen int bufsize = sizeof(EAS_PCM) 208faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen * mEasConfig->mixBufferSize * mEasConfig->numChannels * NUM_COMBINE_BUFFERS; 209faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen ALOGV("using %d byte buffer", bufsize); 210faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mGroup->add_buffer(new MediaBuffer(bufsize)); 211faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen return OK; 212faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} 213faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 214faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissenstatus_t MidiEngine::releaseBuffers() { 215faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen delete mGroup; 216faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mGroup = NULL; 217faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen return OK; 218faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} 219faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 220faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissenstatus_t MidiEngine::seekTo(int64_t positionUs) { 221ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar ALOGV("seekTo %lld", (long long)positionUs); 222faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen EAS_RESULT result = EAS_Locate(mEasData, mEasHandle, positionUs / 1000, false); 223faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen return result == EAS_SUCCESS ? OK : UNKNOWN_ERROR; 224faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} 225faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 226faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco NelissenMediaBuffer* MidiEngine::readBuffer() { 227faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen EAS_STATE state; 228faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen EAS_State(mEasData, mEasHandle, &state); 229faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen if ((state == EAS_STATE_STOPPED) || (state == EAS_STATE_ERROR)) { 230faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen return NULL; 231faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen } 232faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen MediaBuffer *buffer; 233faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen status_t err = mGroup->acquire_buffer(&buffer); 234faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen if (err != OK) { 235faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen ALOGE("readBuffer: no buffer"); 236faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen return NULL; 237faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen } 238faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen EAS_I32 timeMs; 239faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen EAS_GetLocation(mEasData, mEasHandle, &timeMs); 240faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen int64_t timeUs = 1000ll * timeMs; 241faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen buffer->meta_data()->setInt64(kKeyTime, timeUs); 242faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 243faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen EAS_PCM* p = (EAS_PCM*) buffer->data(); 244faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen int numBytesOutput = 0; 245faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen for (int i = 0; i < NUM_COMBINE_BUFFERS; i++) { 246faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen EAS_I32 numRendered; 247faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen EAS_RESULT result = EAS_Render(mEasData, p, mEasConfig->mixBufferSize, &numRendered); 248faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen if (result != EAS_SUCCESS) { 249faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen ALOGE("EAS_Render returned %ld", result); 250faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen break; 251faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen } 252faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen p += numRendered * mEasConfig->numChannels; 253faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen numBytesOutput += numRendered * mEasConfig->numChannels * sizeof(EAS_PCM); 254faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen } 255faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen buffer->set_range(0, numBytesOutput); 256faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen ALOGV("readBuffer: returning %zd in buffer %p", buffer->range_length(), buffer); 257faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen return buffer; 258faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} 259faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 260faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 261faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen// MidiExtractor 262faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 263faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco NelissenMidiExtractor::MidiExtractor( 264faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen const sp<DataSource> &dataSource) 265faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen : mDataSource(dataSource), 266faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mInitCheck(false) 267faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen{ 268faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen ALOGV("MidiExtractor ctor"); 269faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mFileMetadata = new MetaData; 270faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mTrackMetadata = new MetaData; 271faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mEngine = new MidiEngine(mDataSource, mFileMetadata, mTrackMetadata); 272faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen mInitCheck = mEngine->initCheck(); 273faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} 274faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 275faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco NelissenMidiExtractor::~MidiExtractor() 276faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen{ 277faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen ALOGV("MidiExtractor dtor"); 278faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} 279faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 280faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissensize_t MidiExtractor::countTracks() 281faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen{ 282faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen return mInitCheck == OK ? 1 : 0; 283faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} 284faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 285b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissensp<IMediaSource> MidiExtractor::getTrack(size_t index) 286faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen{ 287faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen if (mInitCheck != OK || index > 0) { 288faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen return NULL; 289faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen } 290faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen return new MidiSource(mEngine, mTrackMetadata); 291faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} 292faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 293faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissensp<MetaData> MidiExtractor::getTrackMetaData( 294faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen size_t index, uint32_t /* flags */) { 295faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen ALOGV("MidiExtractor::getTrackMetaData"); 296faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen if (mInitCheck != OK || index > 0) { 297faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen return NULL; 298faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen } 299faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen return mTrackMetadata; 300faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} 301faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 302faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissensp<MetaData> MidiExtractor::getMetaData() 303faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen{ 304faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen ALOGV("MidiExtractor::getMetaData"); 305faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen return mFileMetadata; 306faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} 307faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 308faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen// Sniffer 309faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 310faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissenbool SniffMidi( 311faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen const sp<DataSource> &source, String8 *mimeType, float *confidence, 312faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen sp<AMessage> *) 313faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen{ 314faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen sp<MidiEngine> p = new MidiEngine(source, NULL, NULL); 315faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen if (p->initCheck() == OK) { 316faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen *mimeType = MEDIA_MIMETYPE_AUDIO_MIDI; 317faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen *confidence = 0.8; 318faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen ALOGV("SniffMidi: yes"); 319faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen return true; 320faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen } 321faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen ALOGV("SniffMidi: no"); 322faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen return false; 323faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 324faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} 325faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen 326faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen} // namespace android 327