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();
 }