MidiExtractor.cpp revision b2487f03f12dcafdb801fc0007c8df8412397f44
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);
181faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    }
182faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    mIsInitialized = true;
183faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen}
184faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen
185faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco NelissenMidiEngine::~MidiEngine() {
186faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    if (mEasHandle) {
187faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        EAS_CloseFile(mEasData, mEasHandle);
188faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    }
189faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    if (mEasData) {
190faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        EAS_Shutdown(mEasData);
191faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    }
192faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    delete mGroup;
193faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen
194faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen}
195faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen
196faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissenstatus_t MidiEngine::initCheck() {
197faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    return mIsInitialized ? OK : UNKNOWN_ERROR;
198faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen}
199faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen
200faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissenstatus_t MidiEngine::allocateBuffers() {
201faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    // select reverb preset and enable
202faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_PRESET, EAS_PARAM_REVERB_CHAMBER);
203faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_BYPASS, EAS_FALSE);
204faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen
205faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    mGroup = new MediaBufferGroup;
206faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    int bufsize = sizeof(EAS_PCM)
207faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen            * mEasConfig->mixBufferSize * mEasConfig->numChannels * NUM_COMBINE_BUFFERS;
208faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    ALOGV("using %d byte buffer", bufsize);
209faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    mGroup->add_buffer(new MediaBuffer(bufsize));
210faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    return OK;
211faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen}
212faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen
213faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissenstatus_t MidiEngine::releaseBuffers() {
214faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    delete mGroup;
215faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    mGroup = NULL;
216faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    return OK;
217faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen}
218faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen
219faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissenstatus_t MidiEngine::seekTo(int64_t positionUs) {
220ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar    ALOGV("seekTo %lld", (long long)positionUs);
221faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    EAS_RESULT result = EAS_Locate(mEasData, mEasHandle, positionUs / 1000, false);
222faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    return result == EAS_SUCCESS ? OK : UNKNOWN_ERROR;
223faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen}
224faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen
225faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco NelissenMediaBuffer* MidiEngine::readBuffer() {
226faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    EAS_STATE state;
227faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    EAS_State(mEasData, mEasHandle, &state);
228faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    if ((state == EAS_STATE_STOPPED) || (state == EAS_STATE_ERROR)) {
229faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        return NULL;
230faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    }
231faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    MediaBuffer *buffer;
232faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    status_t err = mGroup->acquire_buffer(&buffer);
233faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    if (err != OK) {
234faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        ALOGE("readBuffer: no buffer");
235faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        return NULL;
236faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    }
237faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    EAS_I32 timeMs;
238faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    EAS_GetLocation(mEasData, mEasHandle, &timeMs);
239faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    int64_t timeUs = 1000ll * timeMs;
240faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    buffer->meta_data()->setInt64(kKeyTime, timeUs);
241faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen
242faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    EAS_PCM* p = (EAS_PCM*) buffer->data();
243faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    int numBytesOutput = 0;
244faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    for (int i = 0; i < NUM_COMBINE_BUFFERS; i++) {
245faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        EAS_I32 numRendered;
246faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        EAS_RESULT result = EAS_Render(mEasData, p, mEasConfig->mixBufferSize, &numRendered);
247faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        if (result != EAS_SUCCESS) {
248faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen            ALOGE("EAS_Render returned %ld", result);
249faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen            break;
250faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        }
251faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        p += numRendered * mEasConfig->numChannels;
252faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        numBytesOutput += numRendered * mEasConfig->numChannels * sizeof(EAS_PCM);
253faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    }
254faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    buffer->set_range(0, numBytesOutput);
255faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    ALOGV("readBuffer: returning %zd in buffer %p", buffer->range_length(), buffer);
256faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    return buffer;
257faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen}
258faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen
259faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen
260faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen// MidiExtractor
261faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen
262faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco NelissenMidiExtractor::MidiExtractor(
263faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        const sp<DataSource> &dataSource)
264faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    : mDataSource(dataSource),
265faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen      mInitCheck(false)
266faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen{
267faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    ALOGV("MidiExtractor ctor");
268faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    mFileMetadata = new MetaData;
269faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    mTrackMetadata = new MetaData;
270faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    mEngine = new MidiEngine(mDataSource, mFileMetadata, mTrackMetadata);
271faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    mInitCheck = mEngine->initCheck();
272faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen}
273faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen
274faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco NelissenMidiExtractor::~MidiExtractor()
275faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen{
276faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    ALOGV("MidiExtractor dtor");
277faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen}
278faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen
279faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissensize_t MidiExtractor::countTracks()
280faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen{
281faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    return mInitCheck == OK ? 1 : 0;
282faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen}
283faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen
284b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissensp<IMediaSource> MidiExtractor::getTrack(size_t index)
285faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen{
286faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    if (mInitCheck != OK || index > 0) {
287faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        return NULL;
288faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    }
289faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    return new MidiSource(mEngine, mTrackMetadata);
290faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen}
291faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen
292faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissensp<MetaData> MidiExtractor::getTrackMetaData(
293faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        size_t index, uint32_t /* flags */) {
294faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    ALOGV("MidiExtractor::getTrackMetaData");
295faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    if (mInitCheck != OK || index > 0) {
296faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        return NULL;
297faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    }
298faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    return mTrackMetadata;
299faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen}
300faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen
301faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissensp<MetaData> MidiExtractor::getMetaData()
302faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen{
303faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    ALOGV("MidiExtractor::getMetaData");
304faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    return mFileMetadata;
305faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen}
306faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen
307faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen// Sniffer
308faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen
309faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissenbool SniffMidi(
310faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        const sp<DataSource> &source, String8 *mimeType, float *confidence,
311faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        sp<AMessage> *)
312faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen{
313faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    sp<MidiEngine> p = new MidiEngine(source, NULL, NULL);
314faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    if (p->initCheck() == OK) {
315faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        *mimeType = MEDIA_MIMETYPE_AUDIO_MIDI;
316faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        *confidence = 0.8;
317faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        ALOGV("SniffMidi: yes");
318faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen        return true;
319faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    }
320faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    ALOGV("SniffMidi: no");
321faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen    return false;
322faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen
323faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen}
324faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen
325faf4efc6a41e88adf85f76f48f020a6d681f5ff1Marco Nelissen}  // namespace android
326