-
Notifications
You must be signed in to change notification settings - Fork 565
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New namespace, constexprs and scoped enums #18
Changes from 5 commits
3bf32ae
2786fb5
89c9076
e5bc9d9
da0edda
379e8e5
93fad7d
338eac6
d4b7f08
5ea2530
605c25c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,24 +48,24 @@ Include the Oboe header: | |
|
||
#include <oboe/Oboe.h> | ||
|
||
Streams are built using an `OboeStreamBuilder`. Create one like this: | ||
Streams are built using an `StreamBuilder`. Create one like this: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. an -> a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Deferring doing the an/a changes until we have made a decision on |
||
|
||
OboeStreamBuilder builder; | ||
oboe::StreamBuilder builder; | ||
|
||
Use the builder's set methods to set properties on the stream (you can read more about these properties in the [full guide](FullGuide.md)): | ||
|
||
builder.setDirection(OBOE_DIRECTION_OUTPUT); | ||
builder.setPerformanceMode(OBOE_PERFORMANCE_MODE_LOW_LATENCY); | ||
builder.setSharingMode(OBOE_SHARING_MODE_EXCLUSIVE); | ||
builder.setDirection(oboe::Direction::Output); | ||
builder.setPerformanceMode(oboe::PerformanceMode::LowLatency); | ||
builder.setSharingMode(oboe::SharingMode::Exclusive); | ||
|
||
Define an `OboeStreamCallback` class to receive callbacks whenever the stream requires new data. | ||
Define an `StreamCallback` class to receive callbacks whenever the stream requires new data. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. an -> a |
||
|
||
class MyCallback : public OboeStreamCallback { | ||
class MyCallback : public oboe::StreamCallback { | ||
public: | ||
oboe_data_callback_result_t | ||
onAudioReady(OboeStream *audioStream, void *audioData, int32_t numFrames){ | ||
oboe::Result | ||
onAudioReady(oboe::Stream *audioStream, void *audioData, int32_t numFrames){ | ||
generateSineWave(static_cast<float *>(audioData), numFrames); | ||
return OBOE_CALLBACK_RESULT_CONTINUE; | ||
return oboe::DataCallbackResult::Continue; | ||
} | ||
}; | ||
|
||
|
@@ -76,21 +76,21 @@ Supply this callback class to the builder: | |
|
||
Open the stream: | ||
|
||
OboeStream *stream; | ||
oboe_result_t result = builder.openStream(&stream); | ||
oboe::Stream *stream; | ||
oboe::Result result = builder.openStream(&stream); | ||
|
||
Check the result to make sure the stream was opened successfully. Oboe has many convenience methods for converting its types into human-readable strings, they all start with `Oboe_convert`: | ||
Check the result to make sure the stream was opened successfully. Oboe has many convenience methods for converting its types into human-readable strings, they all start with `oboe::convert`: | ||
|
||
if (result != OBOE_OK){ | ||
LOGE("Failed to create stream. Error: %s", Oboe_convertResultToText(result)); | ||
if (result != Result::OK){ | ||
LOGE("Failed to create stream. Error: %s", oboe::convertResultToText(result)); | ||
} | ||
|
||
Note that this sample code uses the [logging macros from here](https://github.com/googlesamples/android-audio-high-performance/blob/master/debug-utils/logging_macros.h). | ||
|
||
Check the properties of the created stream. The **format** is one property which you should check. The default is `float` on API 21+ and `int16_t` on API 20 or lower. This will dictate the `audioData` type in the `OboeStreamCallback::onAudioReady` callback. | ||
Check the properties of the created stream. The **format** is one property which you should check. The default is `float` on API 21+ and `int16_t` on API 20 or lower. This will dictate the `audioData` type in the `StreamCallback::onAudioReady` callback. | ||
|
||
oboe_audio_format_t format = stream->getFormat(); | ||
LOGI("Stream format is %s", Oboe_convertAudioFormatToText(format)); | ||
oboe::AudioFormat format = stream->getFormat(); | ||
LOGI("Stream format is %s", oboe::convertAudioFormatToText(format)); | ||
|
||
Now start the stream. | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/* | ||
* Copyright (C) 2016 The Android Open Source Project | ||
* | ||
* 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. | ||
*/ | ||
|
||
#ifndef OBOE_DEFINITIONS_H | ||
#define OBOE_DEFINITIONS_H | ||
|
||
#include <cstdint> | ||
#include <aaudio/AAudio.h> | ||
|
||
namespace oboe { | ||
|
||
constexpr int32_t kUnspecified = 0; | ||
|
||
constexpr int64_t kNanosPerMicrosecond = 1000; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add a TODO to consider using std::chrono, as it provides a lot of time unit conversion utilities. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
constexpr int64_t kNanosPerMillisecond = kNanosPerMicrosecond * 1000; | ||
constexpr int64_t kMillisPerSecond = 1000; | ||
constexpr int64_t kNanosPerSecond = kNanosPerMillisecond * kMillisPerSecond; | ||
|
||
enum class StreamState : aaudio_stream_state_t { | ||
Uninitialized = AAUDIO_STREAM_STATE_UNINITIALIZED, | ||
Open = AAUDIO_STREAM_STATE_OPEN, | ||
Starting = AAUDIO_STREAM_STATE_STARTING, | ||
Started = AAUDIO_STREAM_STATE_STARTED, | ||
Pausing = AAUDIO_STREAM_STATE_PAUSING, | ||
Paused = AAUDIO_STREAM_STATE_PAUSED, | ||
Flushing = AAUDIO_STREAM_STATE_FLUSHING, | ||
Flushed = AAUDIO_STREAM_STATE_FLUSHED, | ||
Stopping = AAUDIO_STREAM_STATE_STOPPING, | ||
Stopped = AAUDIO_STREAM_STATE_STOPPED, | ||
Closing = AAUDIO_STREAM_STATE_CLOSING, | ||
Closed = AAUDIO_STREAM_STATE_CLOSED, | ||
}; | ||
|
||
enum class Direction : aaudio_direction_t { | ||
Output = AAUDIO_DIRECTION_OUTPUT, | ||
Input = AAUDIO_DIRECTION_INPUT, | ||
}; | ||
|
||
enum class AudioFormat : aaudio_format_t { | ||
Invalid = AAUDIO_FORMAT_INVALID, | ||
Unspecified = AAUDIO_FORMAT_UNSPECIFIED, | ||
I16 = AAUDIO_FORMAT_PCM_I16, | ||
Float = AAUDIO_FORMAT_PCM_FLOAT, | ||
}; | ||
|
||
enum class DataCallbackResult : aaudio_data_callback_result_t { | ||
Continue = AAUDIO_CALLBACK_RESULT_CONTINUE, | ||
Stop = AAUDIO_CALLBACK_RESULT_STOP, | ||
}; | ||
|
||
enum class Result : aaudio_result_t { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider renaming this class to "Error", which would allow dropping the "Error" prefix from the enum items. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it normal to have an
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that's perhaps not the best expression. But seeing a lot of "Error" prefixes doesn't make me happy either. Although, I've just checked Vulkan's 'Result' type, and they also have "error" prefixes everywhere. OK, let's not consider changing anything here for now. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are relying on aaudio_result_t beeing int32_t in multiple places. Maybe we should add in some .cpp There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks. Added checks for all AAudio primitive data types. |
||
OK, | ||
ErrorBase = AAUDIO_ERROR_BASE, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ErrorBase shouldn't be used as a source of an assignment anywhere. To prevent this, I would suggest introducing a helper function 'isError' which compares the value against AAUDIO_ERROR_BASE. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why don't I just remove There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. What I've meant is that if anyone will ever need to check against AAUDIO_ERROR_BASE, you can provide a convenience method. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
ErrorDisconnected = AAUDIO_ERROR_DISCONNECTED, | ||
ErrorIllegalArgument = AAUDIO_ERROR_ILLEGAL_ARGUMENT, | ||
ErrorInternal = AAUDIO_ERROR_INTERNAL, | ||
ErrorInvalidState = AAUDIO_ERROR_INVALID_STATE, | ||
ErrorInvalidHandle = AAUDIO_ERROR_INVALID_HANDLE, | ||
ErrorUnimplemented = AAUDIO_ERROR_UNIMPLEMENTED, | ||
ErrorUnavailable = AAUDIO_ERROR_UNAVAILABLE, | ||
ErrorNoFreeHandles = AAUDIO_ERROR_NO_FREE_HANDLES, | ||
ErrorNoMemory = AAUDIO_ERROR_NO_MEMORY, | ||
ErrorNull = AAUDIO_ERROR_NULL, | ||
ErrorTimeout = AAUDIO_ERROR_TIMEOUT, | ||
ErrorWouldBlock = AAUDIO_ERROR_WOULD_BLOCK, | ||
ErrorInvalidFormat = AAUDIO_ERROR_INVALID_FORMAT, | ||
ErrorOutOfRange = AAUDIO_ERROR_OUT_OF_RANGE, | ||
ErrorNoService = AAUDIO_ERROR_NO_SERVICE, | ||
ErrorInvalidRate = AAUDIO_ERROR_INVALID_RATE, | ||
}; | ||
|
||
enum class SharingMode : aaudio_sharing_mode_t { | ||
|
||
/** | ||
* This will be the only stream using a particular source or sink. | ||
* This mode will provide the lowest possible latency. | ||
* You should close EXCLUSIVE streams immediately when you are not using them. | ||
*/ | ||
Exclusive = AAUDIO_SHARING_MODE_EXCLUSIVE, | ||
|
||
/** | ||
* Multiple applications will be mixed by the AAudio Server. | ||
* This will have higher latency than the EXCLUSIVE mode. | ||
*/ | ||
Shared = AAUDIO_SHARING_MODE_SHARED, | ||
}; | ||
|
||
enum class PerformanceMode : aaudio_performance_mode_t { | ||
|
||
// No particular performance needs. Default. | ||
None = AAUDIO_PERFORMANCE_MODE_NONE, | ||
|
||
// Extending battery life is most important. | ||
PowerSaving = AAUDIO_PERFORMANCE_MODE_POWER_SAVING, | ||
|
||
// Reducing latency is most important. | ||
LowLatency = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY | ||
}; | ||
} // namespace oboe | ||
|
||
#endif // OBOE_DEFINITIONS_H |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
c/an/a/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are the class names Stream and StreamBuilder too generic? Is there a danger of colliding if developers are using multiple namespaces?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There would only be a danger if they're using non-qualified namespaces e.g.
using namespace oboe; Stream stream;
But yes, I do think
Stream
is too generic.AudioStream
,AudioStreamBuilder
etc would be more readable. Also if we ever support MIDI we could have aMidiStream
. If you agree I'll rename.