Skip to content
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

Amplify ogg stream? #40

Closed
tgsmith61591 opened this issue Apr 30, 2021 · 2 comments
Closed

Amplify ogg stream? #40

tgsmith61591 opened this issue Apr 30, 2021 · 2 comments

Comments

@tgsmith61591
Copy link

I am new to the audio streaming world, so forgive me if this is a dumb question. My application receives an Ogg stream with Opus data, but the audio is often very quiet. I'm wondering if there is a way for me to amplify each frame by, e.g., 2dB in a streaming fashion?

@hraban
Copy link
Owner

hraban commented Apr 30, 2021

Hi tg,

Welcome to the audio streaming world :)

Sure, that should be easily doable. What you want is the raw PCM data: those represent the individual samples, which are air pressure measurements taken at sequential points in time, e.g. 48 thousand times a second. You could literally create a sine wave with amplitude int16_max ÷ 2 to int16_min ÷ 2, and a period of 48e3/261.626 (iow 261.626 full periods per 48k samples), and if you passed that to an audio device configured to 48khz, you'd have a C. You just created a synthesizer. If you now create another similar sine, but with frequency 391.995Hz, you have a G. If you created a third array, ar, looped over the other two, and literally did ar[i] = c[i] + g[i], you'd have a harmonic fifth.

Add in an E (329.628Hz), and you have a major C chord. However, because you started out at int16_max ÷ 2, and you're summing 3 streams, you could overflow; that's not ok. At the very least, you must do a "saturating sum", i.e. if int16_max - x < y ? int16_max : x + y. This is called "(digital) clipping", and it sounds terrible. This is what you hear when you blow into a mic, or speak too loudly, or have your gain too high.

Tying it all together: what you want is an amplifier. At its core, the algorithm is: for i in range pcm { pcm[i] *= amp } (or, rather: pcm[i] = saturating_mul(pcm[i], amp)). How do you get amp from dB? decibels are a logarithmic scale, and the formula for getting an amplitude factor from gain (which is dB) is amp = 10^(gain/20). Wikipedia and Google have endless more info on this.

The _test files do some actual messing with sine waves, I strongly recommend having a look. I also recommend piping a sine wave through opus and back, dumping the raw PCM out to CSV and plotting that in Excel. You can do the same with any song, and you'll get the actual waveform. It helps make sense of it all.

Hope this helps!

Closing the ticket.

@hraban hraban closed this as completed Apr 30, 2021
@tgsmith61591
Copy link
Author

Wow, thank you so much for such a fantastic response!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants