Refactor to use smart pointers and references where parameters to functions should be non-null.
diff --git a/samples/RhythmGame/src/main/cpp/Game.cpp b/samples/RhythmGame/src/main/cpp/Game.cpp
index d90b75a..5497264 100644
--- a/samples/RhythmGame/src/main/cpp/Game.cpp
+++ b/samples/RhythmGame/src/main/cpp/Game.cpp
@@ -19,7 +19,7 @@
#include "Game.h"
-Game::Game(AAssetManager *assetManager): mAssetManager(assetManager) {
+Game::Game(AAssetManager &assetManager): mAssetManager(assetManager) {
}
void Game::start() {
@@ -31,7 +31,7 @@
LOGE("Could not load source data for clap sound");
return;
}
- mClap = new Player(mClapSource);
+ mClap = std::make_unique<Player>(*mClapSource);
mBackingTrackSource = AAssetDataSource::newFromAssetManager(mAssetManager, "FUNKY_HOUSE.raw",
oboe::ChannelCount::Stereo);
@@ -40,14 +40,14 @@
return;
}
- mBackingTrack = new Player(mBackingTrackSource);
+ mBackingTrack = std::make_unique<Player>(*mBackingTrackSource);
mBackingTrack->setPlaying(true);
mBackingTrack->setLooping(true);
// Add the clap and backing track sounds to a mixer so that they can be played together
// simultaneously using a single audio stream.
- mMixer.addTrack(mClap);
- mMixer.addTrack(mBackingTrack);
+ mMixer.addTrack(*mClap);
+ mMixer.addTrack(*mBackingTrack);
// Add the audio frame numbers on which the clap sound should be played to the clap event queue.
// The backing track tempo is 120 beats per minute, which is 2 beats per second. At a sample
@@ -94,10 +94,9 @@
if (mAudioStream != nullptr){
mAudioStream->close();
+ mAudioStream = nullptr;
}
- delete mClap;
- delete mBackingTrack;
delete mClapSource;
delete mBackingTrackSource;
}
diff --git a/samples/RhythmGame/src/main/cpp/Game.h b/samples/RhythmGame/src/main/cpp/Game.h
index a9154e0..134bf65 100644
--- a/samples/RhythmGame/src/main/cpp/Game.h
+++ b/samples/RhythmGame/src/main/cpp/Game.h
@@ -32,7 +32,7 @@
class Game : public AudioStreamCallback {
public:
- explicit Game(AAssetManager *assetManager);
+ explicit Game(AAssetManager&);
void start();
void stop();
@@ -47,13 +47,12 @@
onAudioReady(AudioStream *oboeStream, void *audioData, int32_t numFrames) override;
private:
- AAssetManager *mAssetManager{nullptr};
+ AAssetManager& mAssetManager;
AudioStream *mAudioStream{nullptr};
-
AAssetDataSource *mClapSource{nullptr};
AAssetDataSource *mBackingTrackSource{nullptr};
- Player *mClap{nullptr};
- Player *mBackingTrack{nullptr};
+ std::unique_ptr<Player> mClap;
+ std::unique_ptr<Player> mBackingTrack;
Mixer mMixer;
LockFreeQueue<int64_t, kMaxQueueItems> mClapEvents;
diff --git a/samples/RhythmGame/src/main/cpp/audio/AAssetDataSource.cpp b/samples/RhythmGame/src/main/cpp/audio/AAssetDataSource.cpp
index 2f542f6..0d6dbc4 100644
--- a/samples/RhythmGame/src/main/cpp/audio/AAssetDataSource.cpp
+++ b/samples/RhythmGame/src/main/cpp/audio/AAssetDataSource.cpp
@@ -19,12 +19,12 @@
#include "AAssetDataSource.h"
-AAssetDataSource* AAssetDataSource::newFromAssetManager(AAssetManager *assetManager,
+AAssetDataSource* AAssetDataSource::newFromAssetManager(AAssetManager &assetManager,
const char *filename,
const int32_t channelCount) {
// Load the backing track
- AAsset* asset = AAssetManager_open(assetManager, filename, AASSET_MODE_BUFFER);
+ AAsset* asset = AAssetManager_open(&assetManager, filename, AASSET_MODE_BUFFER);
if (asset == nullptr){
LOGE("Failed to open track, filename %s", filename);
@@ -32,7 +32,7 @@
}
// Get the length of the track (we assume it is stereo 48kHz)
- off_t trackLength = AAsset_getLength(asset);
+ off_t trackSizeInBytes = AAsset_getLength(asset);
// Load it into memory
auto *audioBuffer = static_cast<const int16_t*>(AAsset_getBuffer(asset));
@@ -42,11 +42,8 @@
return nullptr;
}
- // There are 4 bytes per frame because
- // each sample is 2 bytes and
- // it's a stereo recording which has 2 samples per frame.
- int32_t numFrames = static_cast<int32_t>(trackLength / 4);
- LOGD("Opened backing track, bytes: %ld frames: %d", trackLength, numFrames);
+ auto numFrames = static_cast<int32_t>(trackSizeInBytes / (sizeof(int16_t) * channelCount));
+ LOGD("Opened audio data source, bytes: %ld frames: %d", trackSizeInBytes, numFrames);
return new AAssetDataSource(asset, audioBuffer, numFrames, channelCount);
}
diff --git a/samples/RhythmGame/src/main/cpp/audio/AAssetDataSource.h b/samples/RhythmGame/src/main/cpp/audio/AAssetDataSource.h
index 53d4c28..dd64650 100644
--- a/samples/RhythmGame/src/main/cpp/audio/AAssetDataSource.h
+++ b/samples/RhythmGame/src/main/cpp/audio/AAssetDataSource.h
@@ -30,12 +30,11 @@
AAsset_close(mAsset);
}
- int32_t getTotalFrames() override { return mTotalFrames; } ;
- int32_t getChannelCount() override { return mChannelCount; } ;
- virtual const int16_t* getData() override { return mBuffer; };
+ int32_t getTotalFrames() const override { return mTotalFrames; } ;
+ int32_t getChannelCount() const override { return mChannelCount; } ;
+ const int16_t* getData() const override { return mBuffer; };
- static AAssetDataSource* newFromAssetManager(AAssetManager *assetManager, const char *filename,
- const int32_t channelCount);
+ static AAssetDataSource* newFromAssetManager(AAssetManager&, const char *, const int32_t);
private:
@@ -49,7 +48,7 @@
AAsset *mAsset = nullptr;
const int16_t* mBuffer;
- int32_t mTotalFrames;
+ const int32_t mTotalFrames;
const int32_t mChannelCount;
};
diff --git a/samples/RhythmGame/src/main/cpp/audio/DataSource.h b/samples/RhythmGame/src/main/cpp/audio/DataSource.h
index b0bf01a..6694399 100644
--- a/samples/RhythmGame/src/main/cpp/audio/DataSource.h
+++ b/samples/RhythmGame/src/main/cpp/audio/DataSource.h
@@ -22,9 +22,9 @@
class DataSource {
public:
virtual ~DataSource(){};
- virtual int32_t getTotalFrames() = 0;
- virtual int32_t getChannelCount() = 0;
- virtual const int16_t* getData() = 0;
+ virtual int32_t getTotalFrames() const = 0;
+ virtual int32_t getChannelCount() const = 0;
+ virtual const int16_t* getData() const = 0;
};
diff --git a/samples/RhythmGame/src/main/cpp/audio/Mixer.cpp b/samples/RhythmGame/src/main/cpp/audio/Mixer.cpp
index 0279617..a64f36b 100644
--- a/samples/RhythmGame/src/main/cpp/audio/Mixer.cpp
+++ b/samples/RhythmGame/src/main/cpp/audio/Mixer.cpp
@@ -24,7 +24,7 @@
}
for (int i = 0; i < mNextFreeTrackIndex; ++i) {
- mTracks[i]->renderAudio(mixingBuffer, numFrames);
+ mTracks[i]->renderAudio(mixingBuffer.data(), numFrames);
for (int j = 0; j < numFrames * kChannelCount; ++j) {
audioData[j] += mixingBuffer[j];
@@ -32,6 +32,8 @@
}
}
-void Mixer::addTrack(RenderableAudio *renderer){
- mTracks[mNextFreeTrackIndex++] = renderer;
+void Mixer::addTrack(RenderableAudio &renderer){
+ mTracks[mNextFreeTrackIndex++] = &renderer;
+ // If we've reached our track limit then overwrite the first track
+ if (mNextFreeTrackIndex >= kMaxTracks) mNextFreeTrackIndex = 0;
};
\ No newline at end of file
diff --git a/samples/RhythmGame/src/main/cpp/audio/Mixer.h b/samples/RhythmGame/src/main/cpp/audio/Mixer.h
index 2a09fca..8dcf152 100644
--- a/samples/RhythmGame/src/main/cpp/audio/Mixer.h
+++ b/samples/RhythmGame/src/main/cpp/audio/Mixer.h
@@ -28,12 +28,12 @@
class Mixer : public RenderableAudio {
public:
- void addTrack(RenderableAudio *renderer);
+ void addTrack(RenderableAudio&);
void renderAudio(int16_t *audioData, int32_t numFrames);
private:
- int16_t *mixingBuffer = new int16_t[kBufferSize]; // TODO: smart pointer
+ std::array<int16_t, kBufferSize> mixingBuffer;
RenderableAudio *mTracks[kMaxTracks]; // TODO: this might be better as a linked list for easy track removal
uint8_t mNextFreeTrackIndex = 0;
};
diff --git a/samples/RhythmGame/src/main/cpp/audio/Player.cpp b/samples/RhythmGame/src/main/cpp/audio/Player.cpp
index 7470e40..df6fe0d 100644
--- a/samples/RhythmGame/src/main/cpp/audio/Player.cpp
+++ b/samples/RhythmGame/src/main/cpp/audio/Player.cpp
@@ -19,30 +19,41 @@
void Player::renderAudio(int16_t *targetData, int32_t numFrames){
+ const int32_t channelCount = mSource.getChannelCount();
+
if (mIsPlaying){
- int32_t totalFrames = mSource->getTotalFrames();
- const int16_t *data = mSource->getData();
+ int32_t framesToRenderFromData = numFrames;
+ int32_t totalSourceFrames = mSource.getTotalFrames();
+ const int16_t *data = mSource.getData();
// Check whether we're about to reach the end of the recording
- if (!mIsLooping && mReadFrameIndex + numFrames >= totalFrames){
- numFrames = totalFrames - mReadFrameIndex;
+ if (!mIsLooping && mReadFrameIndex + numFrames >= totalSourceFrames){
+ framesToRenderFromData = totalSourceFrames - mReadFrameIndex;
mIsPlaying = false;
}
- for (int i = 0; i < numFrames; ++i) {
- for (int j = 0; j < mChannelCount; ++j) {
- targetData[(i*mChannelCount)+j] = data[(mReadFrameIndex*mChannelCount)+j];
+ for (int i = 0; i < framesToRenderFromData; ++i) {
+ for (int j = 0; j < channelCount; ++j) {
+ targetData[(i*channelCount)+j] = data[(mReadFrameIndex*channelCount)+j];
}
// Increment and handle wraparound
- if (++mReadFrameIndex >= totalFrames) mReadFrameIndex = 0;
+ if (++mReadFrameIndex >= totalSourceFrames) mReadFrameIndex = 0;
+ }
+
+ if (framesToRenderFromData < numFrames){
+ // fill the rest of the buffer with silence
+ renderSilence(&targetData[framesToRenderFromData], numFrames * channelCount);
}
} else {
- // fill with zeros to output silence
- for (int i = 0; i < numFrames * mChannelCount; ++i) {
- targetData[i] = 0;
- }
+ renderSilence(targetData, numFrames * channelCount);
+ }
+}
+
+void Player::renderSilence(int16_t *start, int32_t numSamples){
+ for (int i = 0; i < numSamples; ++i) {
+ start[i] = 0;
}
}
\ No newline at end of file
diff --git a/samples/RhythmGame/src/main/cpp/audio/Player.h b/samples/RhythmGame/src/main/cpp/audio/Player.h
index 39ac9ca..dc6c3f9 100644
--- a/samples/RhythmGame/src/main/cpp/audio/Player.h
+++ b/samples/RhythmGame/src/main/cpp/audio/Player.h
@@ -39,9 +39,8 @@
*
* @param source
*/
- Player(DataSource *source)
+ Player(DataSource &source)
: mSource(source)
- , mChannelCount(source->getChannelCount())
{};
void renderAudio(int16_t *targetData, int32_t numFrames);
@@ -53,9 +52,9 @@
int32_t mReadFrameIndex = 0;
std::atomic<bool> mIsPlaying { false };
std::atomic<bool> mIsLooping { false };
+ DataSource &mSource;
- DataSource *mSource;
- int32_t mChannelCount;
+ void renderSilence(int16_t*, int32_t);
};
diff --git a/samples/RhythmGame/src/main/cpp/native-lib.cpp b/samples/RhythmGame/src/main/cpp/native-lib.cpp
index e2028ea..ecd941f 100644
--- a/samples/RhythmGame/src/main/cpp/native-lib.cpp
+++ b/samples/RhythmGame/src/main/cpp/native-lib.cpp
@@ -31,7 +31,12 @@
jobject jAssetManager) {
AAssetManager *assetManager = AAssetManager_fromJava(env, jAssetManager);
- game = std::make_unique<Game>(assetManager);
+ if (assetManager == nullptr) {
+ LOGE("Could not obtain the AAssetManager");
+ return;
+ }
+
+ game = std::make_unique<Game>(*assetManager);
game->start();
}