-
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
Add RhythmGame sample #75
Conversation
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.
Sorry for a delay. This is a big change.
mMixer.addTrack(mClap); | ||
mMixer.addTrack(mBackingTrack); | ||
|
||
mClapEvents.push(0); |
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.
Please provide a comment why we are doing this.
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.
Done
mClapWindows.push(144000); | ||
|
||
AudioStreamBuilder builder; | ||
builder.setFormat(AudioFormat::I16); |
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.
Since setters of AudioStreamBuilder return a pointer to it, it's possible to chain these calls.
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.
True but chaining the calls makes the code less maintainable because it's slightly more difficult to add and remove stream properties. Is there any advantage, other than not prefixing with builder.
?
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.
Omitting 'builder' removes clutter, so the code is easier to read. If you choose the first parameter to be something that is always needed to be set, and use a line per chained call, then adding / removing setters is no more difficult than in your version. Compare:
builder.setA();
builder.setB();
builder.setC();
builder.setA()
->setB()
->setC();
[Personally I would prefer setters that return "*this", so it's always "." prefix, but I guess we are stuck with what we have.]
But finally, up to you—there is no style guide for this.
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.
When you add a setter you need to remove the trailing ;
from the last line (in this case ->setC();
so there is some marginal extra overhead. Also, I find the difference between the initial .
and subsequent ->
s to be more visually cluttering (and slightly more confusing: "oh wait, a set method returns a pointer?") than the multiple instances of builder.
. Not that bothered either way, but will probably leave as is.
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.
Sure. I agree that returning a pointer from the setters hurts the looks of client code.
|
||
builder.openStream(&mAudioStream); | ||
|
||
mAudioStream->setBufferSizeInFrames(mAudioStream->getFramesPerBurst() * 2); |
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 you deliberately skipping checks for stream validity here?
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.
I was deliberately skipping them when I live coded this example, however I shouldn't in this official sample. Fixed.
if (mClapWindows.pop(nextClapWindowFrame)){ | ||
|
||
int64_t frameDelta = nextClapWindowFrame - mCurrentFrame; | ||
int64_t timeDelta = convertFramesToMillis(frameDelta, 48000); |
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.
48000 should be some game-wide constant since you even mention it in the project description as the current limitation.
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.
Done
if (mUiEvents.pop(r)) { | ||
renderEvent(r); | ||
} else { | ||
SetGLScreenColor(GREY); |
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.
This should be a constant in case anyone would like to customize the color scheme.
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.
Done
#include <android/log.h> | ||
#include <vector> | ||
|
||
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, "rhythm_game", __VA_ARGS__)) |
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.
Create a define for the tag name.
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.
Done
|
||
@Override | ||
public void surfaceDestroyed(SurfaceHolder holder) { | ||
super.surfaceDestroyed(holder); |
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.
Does it make sense to run our code first, and then the base class code in this case?
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.
Yes, it probably does. Changed.
super(context); | ||
|
||
// Create an OpenGL ES context | ||
/*if(BuildConfig.FLAVOR.equals("GL_3")) |
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.
Please remove commented out code for clarity.
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.
Done
@@ -0,0 +1,41 @@ | |||
/* | |||
* Copyright 2017 Google Inc. |
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.
2018, AOSP?
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.
Done
* - read/writes correct after wraparound (takes too long to run) | ||
* - Constructing queue with non power of 2 capacity results in assert failure (needs death test) | ||
* - Constructing queue with signed type results in assert failure (needs death test) | ||
* - Multi-threaded read/writes (complicated to test) |
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.
MT is essential to test here, otherwise there is a big risk of running into very confusing problems at run time only.
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.
Done
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.
Looks good, just a few more comments.
Please decide what to do with your queue. It seems that you are planning to replace it with the one from Oboe.
// This defines the size of the tap window in milliseconds. For example, if defined at 100ms the | ||
// player will have 100ms before and after the centre of the tap window to tap on the screen and | ||
// be successful | ||
constexpr int kWindowCenterOffset = 100; |
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.
Please add "Ms" suffix.
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.
Done
#include "utils/LockFreeQueue.h" | ||
#include "utils/UtilityFunctions.h" | ||
|
||
constexpr int kSampleRate = 48000; // Fixed sample rate, see README |
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.
Please add "Hz" suffix.
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.
Done
|
||
|
||
#include <cstdint> | ||
|
||
class RenderableAudio { | ||
|
||
public: | ||
virtual ~RenderableAudio(){}; |
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.
nit: It is recommended to put "= default" instead of using empty body.
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.
Done. nits = better code 👍
mClapWindows.push(144000); | ||
|
||
AudioStreamBuilder builder; | ||
builder.setFormat(AudioFormat::I16); |
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.
Sure. I agree that returning a pointer from the setters hurts the looks of client code.
Adding a new sample which shows how to create a simple musical game. Please read the README before reviewing:
https://github.com/google/oboe/tree/rhythmgame/samples/RhythmGame
The main files which need reviewing are:
samples/RhythmGame/README.md
samples/RhythmGame/src/main/cpp/*