1 /*
2  * Copyright 2018 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 #ifndef RHYTHMGAME_GAME_H
18 #define RHYTHMGAME_GAME_H
19 
20 #include <future>
21 
22 #include <android/asset_manager.h>
23 #include <oboe/Oboe.h>
24 
25 #include "shared/Mixer.h"
26 
27 #include "audio/Player.h"
28 #include "audio/AAssetDataSource.h"
29 #include "ui/OpenGLFunctions.h"
30 #include "utils/LockFreeQueue.h"
31 #include "utils/UtilityFunctions.h"
32 #include "GameConstants.h"
33 
34 using namespace oboe;
35 
36 
37 enum class GameState {
38     Loading,
39     Playing,
40     FailedToLoad
41 };
42 
43 class Game : public AudioStreamCallback {
44 public:
45     explicit Game(AAssetManager&);
46     void start();
47     void stop();
48     void onSurfaceCreated();
49     void onSurfaceDestroyed();
50     void onSurfaceChanged(int widthInPixels, int heightInPixels);
51     void tick();
52     void tap(int64_t eventTimeAsUptime);
53 
54     // Inherited from oboe::AudioStreamDataCallback
55     DataCallbackResult
56     onAudioReady(AudioStream *oboeStream, void *audioData, int32_t numFrames) override;
57 
58     // Inherited from oboe::AudioStreamErrorCallback
59     void onErrorAfterClose(AudioStream *oboeStream, Result error) override;
60 
61 private:
62     AAssetManager& mAssetManager;
63     std::shared_ptr<AudioStream> mAudioStream;
64     std::unique_ptr<Player> mClap;
65     std::unique_ptr<Player> mBackingTrack;
66     Mixer mMixer;
67     std::unique_ptr<float[]> mConversionBuffer { nullptr }; // For float->int16 conversion
68 
69     LockFreeQueue<int64_t, kMaxQueueItems> mClapEvents;
70     std::atomic<int64_t> mCurrentFrame { 0 };
71     std::atomic<int64_t> mSongPositionMs { 0 };
72     LockFreeQueue<int64_t, kMaxQueueItems> mClapWindows;
73     LockFreeQueue<TapResult, kMaxQueueItems> mUiEvents;
74     std::atomic<int64_t> mLastUpdateTime { 0 };
75     std::atomic<GameState> mGameState { GameState::Loading };
76     std::future<void> mLoadingResult;
77 
78     void load();
79     TapResult getTapResult(int64_t tapTimeInMillis, int64_t tapWindowInMillis);
80     bool openStream();
81     bool setupAudioSources();
82     void scheduleSongEvents();
83 };
84 
85 
86 #endif //RHYTHMGAME_GAME_H
87