-
Notifications
You must be signed in to change notification settings - Fork 27
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 CEF audio rerouting to audio_data signal #31
Conversation
@@ -458,6 +498,11 @@ class GDBrowserView : public godot::Node | |||
godot::Ref<godot::Image> m_image; | |||
godot::PoolByteArray m_data; | |||
|
|||
// Audio | |||
godot::PoolVector2Array audioBuffer; |
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 use "m_" (m_audioBuffer) for member variables.
@@ -458,6 +498,11 @@ class GDBrowserView : public godot::Node | |||
godot::Ref<godot::Image> m_image; | |||
godot::PoolByteArray m_data; | |||
|
|||
// Audio | |||
godot::PoolVector2Array audioBuffer; | |||
int audioChannelLayoutSize = -1; |
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.
Cannot be size_t and set to 0 instead of int ?
@@ -434,6 +468,12 @@ class GDBrowserView : public godot::Node | |||
CefRenderHandler::PaintElementType type, | |||
const CefRenderHandler::RectList& dirtyRects, | |||
const void* buffer, int width, int height); | |||
|
|||
void onAudioStart(CefRefPtr<CefBrowser> browser, |
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 indent to follow my coding style
@@ -434,6 +468,12 @@ class GDBrowserView : public godot::Node | |||
CefRenderHandler::PaintElementType type, | |||
const CefRenderHandler::RectList& dirtyRects, | |||
const void* buffer, int width, int height); | |||
|
|||
void onAudioStart(CefRefPtr<CefBrowser> browser, | |||
const CefAudioParameters& params, int channels); |
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.
Cannot channels be size_t instead ?
addons/gdcef/gdcef/src/gdbrowser.cpp
Outdated
@@ -176,6 +177,37 @@ void GDBrowserView::onPaint(CefRefPtr<CefBrowser> /*browser*/, | |||
m_texture->create_from_image(m_image, godot::Texture::FLAG_VIDEO_SURFACE); | |||
} | |||
|
|||
|
|||
//------------------------------------------------------------------------------ | |||
/// Called on the audio stream thread when a PCM packet is received for the |
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 use //! \brief instead of /// and move this inside the header file on the associated method
|
||
audioBuffer.resize(frames); | ||
for (int i = 0; i < frames; i++){ | ||
audioBuffer.set(i, godot::Vector2(data[0][i], data[0][i])); |
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 sure of Vector2(data[0][i], data[0][i]) ? Should not be Vector2(data[i][0], data[i][1]) instead ?
addons/gdcef/gdcef/src/gdbrowser.cpp
Outdated
} | ||
|
||
audioBuffer.resize(frames); | ||
for (int i = 0; i < frames; i++){ |
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.
Can you break the line before { to follow my coding style ?
addons/gdcef/gdcef/src/gdbrowser.cpp
Outdated
void GDBrowserView::onAudio(CefRefPtr<CefBrowser> browser, | ||
const float** data, int frames, int64 pts) | ||
{ | ||
if (data == nullptr || frames == 0 || audioChannelLayoutSize == -1) { |
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 would prefer:
if ((data == nullptr) || (frames < 0) ||( audioChannelLayoutSize == 0))
because:
- frames is int but used as unsigned
- audioChannelLayoutSize shall not be 0 when no channel used ?
return; | ||
} | ||
|
||
audioBuffer.resize(frames); |
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.
audioBuffer.resize(size_t(frames)); else the compiler probably complains of possible negative values
addons/gdcef/gdcef/src/gdbrowser.cpp
Outdated
void GDBrowserView::onAudioStart(CefRefPtr<CefBrowser> browser, | ||
const CefAudioParameters& params, int channels) | ||
{ | ||
audioChannelLayoutSize = (int)params.channel_layout; |
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.
(int) is C cast, not C++, the compiler will complain.
Why not audioChannelLayoutSize = size_t(params.channel_layout);
and audioChannelLayoutSize seems not be used.
@parulina Thank you for your pull request! I'm not sure to understand what is the utility of rerouting the sound (for doing signal processing ?), but why not ! I made reviews. Feel free to modify the 2D demo https://github.com/Lecrapouille/gdcef/tree/master/addons/gdcef/demos/2D by adding your example. The 2D demo is made for showing the most features of this module, like a sandbox. PS: I give a try: I hear no sound :( and I have an error inside your callback when halting the demo2D. In addition, the rerouting pipeline should be set only if desired by the user when creating a browser |
@@ -131,6 +132,11 @@ class GDBrowserView : public godot::Node | |||
return this; | |||
} | |||
|
|||
virtual CefRefPtr<CefAudioHandler> GetAudioHandler() override | |||
{ | |||
return 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.
This code will force using your audio callback. I do not like that since your code is still experimental and this force to add a AudioStreamPlayer3D node in all projects. I would return this
if and only if godot::Dictionary browser_settings
has a field {"audio_rerouting", STATE_ENABLED}
else return nullptr
to use the default sound pipeline.
See:
gdcef/addons/gdcef/gdcef/src/gdcef.hpp
Lines 243 to 264 in 4b0fac5
// ------------------------------------------------------------------------- | |
//! \brief Create a browser view and store its instance inside the internal | |
//! container. Return the browser identifier or return nullptr in case of failure. | |
//! \param[in] url the page link (by copy needed by Godot). | |
//! \param[in] name the browser name (by copy needed by Godot). | |
//! \param[in] w the width dimension of the document. | |
//! \param[in] h the height dimension of the document. | |
//! \param[in] Return the address of the newly created browser (or nullptr | |
//! in case of error). | |
//! \param[in] browser_settings dictionary of Browser config with default values: | |
//! - {"frame_rate", 30} | |
//! - {"javascript", STATE_ENABLED} | |
//! - {"javascript_close_windows", STATE_DISABLED} | |
//! - {"javascript_access_clipboard", STATE_DISABLED} | |
//! - {"javascript_dom_paste", STATE_DISABLED} | |
//! - {"image_loading", STATE_ENABLED} | |
//! - {"databases", STATE_ENABLED} | |
//! - {"webgl", STATE_ENABLED} | |
//! Wherer STATE_DISABLED / STATE_ENABLED == false / true | |
// ------------------------------------------------------------------------- | |
GDBrowserView* createBrowser(godot::String const url, godot::String const name, | |
int w, int h, godot::Dictionary browser_settings); |
Thank you for the detailed feedback, useful to know what parts exactly to improve. I agree about the optional parameter. I can get back with the added improvements in a bit and double check if the demo would work.
Similar to showing the CEF texture on a mesh in-game, this allows you to route the audio CEF produces to AudioStreamPlayer or AudioStreamPlayer3D, making the audio play in the game instead of from the subprocess, I give an example: This is a game recording, normally this recording would exclude the played audio since CEF is a separate process. I route the CEF audio to my game's audio bus that also has spectrum analyzer, so that's how I can add visualizer at the bottom left as well as do subtle camera effects like screen shake or bloom depending on the lower frequencies like drums etc. Routing the audio ingame also allows the user to change the volume in-game rather than having to adjust the volume of the subprocess (at least in Windows you have to right click audio device > volume mixer, find the cryptic "gdcefSubprocess.exe" with no icon, adjust its volume that it will also forget) making it more user friendly. |
@pixaline Any news ? |
106ef68
to
6a95ae8
Compare
@pixaline sorry I crapped the merged conflict, I do not how to use this poor Github UX. Commited manually |
Based on PR made by pixaline #31
Update 2d with AudioStreamPlayer2D and 3d demos with AudioStreamPlayer3D
Update 2d with AudioStreamPlayer2D and 3d demos with AudioStreamPlayer3D
Hello there,
I found myself wanting to route the audio produced by CEF in to Godot. I implemented some prototype code from skimming other open source projects. I intend this to be a starting point for something better, perhaps added comments, audio buffer, or a toggle to toggle it on or off. The code only plays mono audio for now.
You can use this in Godot with the following example code: