Don Turner | ca6f91a | 2017-09-05 14:52:39 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2016 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #include "oboe/Oboe.h" |
| 18 | |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 19 | #include "opensles/AudioStreamBuffered.h" |
Don Turner | ca6f91a | 2017-09-05 14:52:39 +0100 | [diff] [blame] | 20 | #include "common/AudioClock.h" |
| 21 | |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 22 | namespace oboe { |
| 23 | |
Don Turner | ca6f91a | 2017-09-05 14:52:39 +0100 | [diff] [blame] | 24 | /* |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 25 | * AudioStream with a FifoBuffer |
Don Turner | ca6f91a | 2017-09-05 14:52:39 +0100 | [diff] [blame] | 26 | */ |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 27 | AudioStreamBuffered::AudioStreamBuffered(const AudioStreamBuilder &builder) |
Phil Burk | 373e646 | 2018-02-07 20:37:17 -0800 | [diff] [blame^] | 28 | : AudioStream(builder) { |
| 29 | } |
| 30 | AudioStreamBuffered::~AudioStreamBuffered() { |
| 31 | delete mFifoBuffer; |
Don Turner | ca6f91a | 2017-09-05 14:52:39 +0100 | [diff] [blame] | 32 | } |
| 33 | |
Phil Burk | 373e646 | 2018-02-07 20:37:17 -0800 | [diff] [blame^] | 34 | Result AudioStreamBuffered::finishOpen() { |
Don Turner | ca6f91a | 2017-09-05 14:52:39 +0100 | [diff] [blame] | 35 | // If the caller does not provide a callback use our own internal |
| 36 | // callback that reads data from the FIFO. |
Don Turner | d4b7f08 | 2017-12-01 13:51:54 +0000 | [diff] [blame] | 37 | if (getCallback() == nullptr) { |
Phil Burk | 373e646 | 2018-02-07 20:37:17 -0800 | [diff] [blame^] | 38 | LOGD("AudioStreamBuffered(): new FifoBuffer(bytesPerFrame=%d", getBytesPerFrame()); |
| 39 | // FIFO is configured with the same format and channels as the stream. |
Don Turner | ca6f91a | 2017-09-05 14:52:39 +0100 | [diff] [blame] | 40 | mFifoBuffer = new FifoBuffer(getBytesPerFrame(), 1024); // TODO size? |
| 41 | // Create a callback that reads from the FIFO |
Don Turner | 056fe73 | 2017-12-04 13:59:22 +0000 | [diff] [blame] | 42 | mInternalCallback = std::unique_ptr<AudioStreamBufferedCallback>(new AudioStreamBufferedCallback(this)); |
Don Turner | d4b7f08 | 2017-12-01 13:51:54 +0000 | [diff] [blame] | 43 | mStreamCallback = mInternalCallback.get(); |
| 44 | LOGD("AudioStreamBuffered(): mStreamCallback = %p", mStreamCallback); |
Don Turner | ca6f91a | 2017-09-05 14:52:39 +0100 | [diff] [blame] | 45 | } |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 46 | return Result::OK; |
Don Turner | ca6f91a | 2017-09-05 14:52:39 +0100 | [diff] [blame] | 47 | } |
| 48 | |
Phil Burk | 373e646 | 2018-02-07 20:37:17 -0800 | [diff] [blame^] | 49 | // TODO: This method should return a tuple of Result,int32_t where the |
| 50 | // 2nd return param is the frames written. Maybe not! |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 51 | int32_t AudioStreamBuffered::write(const void *buffer, |
Phil Burk | 373e646 | 2018-02-07 20:37:17 -0800 | [diff] [blame^] | 52 | int32_t numFrames, |
| 53 | int64_t timeoutNanoseconds) |
Don Turner | ca6f91a | 2017-09-05 14:52:39 +0100 | [diff] [blame] | 54 | { |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 55 | int32_t result = 0; |
Don Turner | ca6f91a | 2017-09-05 14:52:39 +0100 | [diff] [blame] | 56 | uint8_t *source = (uint8_t *)buffer; |
| 57 | int32_t framesLeft = numFrames; |
| 58 | while(framesLeft > 0 && result >= 0) { |
Phil Burk | 373e646 | 2018-02-07 20:37:17 -0800 | [diff] [blame^] | 59 | result = mFifoBuffer->write(source, framesLeft); |
| 60 | LOGD("AudioStreamBuffered::%s(): wrote %d / %d frames to FIFO, [0] = %f", |
| 61 | __func__, result, framesLeft, ((float *)source)[0]); |
Don Turner | ca6f91a | 2017-09-05 14:52:39 +0100 | [diff] [blame] | 62 | if (result > 0) { |
| 63 | source += mFifoBuffer->convertFramesToBytes(result); |
| 64 | incrementFramesWritten(result); |
| 65 | framesLeft -= result; |
| 66 | } |
| 67 | if (framesLeft > 0 && result >= 0) { |
| 68 | int64_t wakeTimeNanos = mFifoBuffer->getNextReadTime(getSampleRate()); |
| 69 | // TODO use timeoutNanoseconds |
| 70 | AudioClock::sleepUntilNanoTime(wakeTimeNanos); |
| 71 | } |
| 72 | } |
| 73 | return result; |
| 74 | } |
| 75 | |
Phil Burk | 373e646 | 2018-02-07 20:37:17 -0800 | [diff] [blame^] | 76 | // Read from the FIFO that was written by the callback. |
| 77 | int32_t AudioStreamBuffered::read(void *buffer, |
| 78 | int32_t numFrames, |
| 79 | int64_t timeoutNanoseconds) |
| 80 | { |
| 81 | static int readCount = 0; |
| 82 | int32_t result = 0; |
| 83 | uint8_t *destination = (uint8_t *)buffer; |
| 84 | int32_t framesLeft = numFrames; |
| 85 | while(framesLeft > 0 && result >= 0) { |
| 86 | result = mFifoBuffer->read(destination, framesLeft); |
| 87 | LOGD("AudioStreamBuffered::%s(): read %d/%d frames from FIFO, #%d", |
| 88 | __func__, result, framesLeft, readCount); |
| 89 | if (result > 0) { |
| 90 | destination += mFifoBuffer->convertFramesToBytes(result); |
| 91 | incrementFramesRead(result); |
| 92 | framesLeft -= result; |
| 93 | readCount++; |
| 94 | } |
| 95 | if (framesLeft > 0 && result >= 0) { |
| 96 | // FIXME use proper timing model, borrow one from AAudio |
| 97 | // TODO use timeoutNanoseconds |
| 98 | AudioClock::sleepForNanos(4 * kNanosPerMillisecond); |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | return result; |
| 103 | } |
| 104 | |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 105 | Result AudioStreamBuffered::setBufferSizeInFrames(int32_t requestedFrames) |
Don Turner | ca6f91a | 2017-09-05 14:52:39 +0100 | [diff] [blame] | 106 | { |
| 107 | if (mFifoBuffer != nullptr) { |
| 108 | if (requestedFrames > mFifoBuffer->getBufferCapacityInFrames()) { |
| 109 | requestedFrames = mFifoBuffer->getBufferCapacityInFrames(); |
| 110 | } |
| 111 | mFifoBuffer->setThresholdFrames(requestedFrames); |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 112 | return Result::OK; |
Don Turner | ca6f91a | 2017-09-05 14:52:39 +0100 | [diff] [blame] | 113 | } else { |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 114 | return Result::ErrorUnimplemented; |
Don Turner | ca6f91a | 2017-09-05 14:52:39 +0100 | [diff] [blame] | 115 | } |
| 116 | } |
| 117 | |
| 118 | |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 119 | int32_t AudioStreamBuffered::getBufferSizeInFrames() const { |
Don Turner | ca6f91a | 2017-09-05 14:52:39 +0100 | [diff] [blame] | 120 | if (mFifoBuffer != nullptr) { |
| 121 | return mFifoBuffer->getThresholdFrames(); |
| 122 | } else { |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 123 | return AudioStream::getBufferSizeInFrames(); |
Don Turner | ca6f91a | 2017-09-05 14:52:39 +0100 | [diff] [blame] | 124 | } |
| 125 | } |
| 126 | |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 127 | int32_t AudioStreamBuffered::getBufferCapacityInFrames() const { |
Don Turner | ca6f91a | 2017-09-05 14:52:39 +0100 | [diff] [blame] | 128 | if (mFifoBuffer != nullptr) { |
| 129 | return mFifoBuffer->getBufferCapacityInFrames(); // Maybe set mBufferCapacity in constructor |
| 130 | } else { |
Don Turner | 379e8e5 | 2017-11-29 15:49:29 +0000 | [diff] [blame] | 131 | return AudioStream::getBufferCapacityInFrames(); |
Don Turner | ca6f91a | 2017-09-05 14:52:39 +0100 | [diff] [blame] | 132 | } |
| 133 | } |
Don Turner | 3bf32ae | 2017-11-27 13:25:05 +0000 | [diff] [blame] | 134 | |
| 135 | } // namespace oboe |