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

Feature Request: Replaygain or Normalization #1099

Closed
Silun opened this issue May 20, 2016 · 37 comments
Closed

Feature Request: Replaygain or Normalization #1099

Silun opened this issue May 20, 2016 · 37 comments

Comments

@Silun
Copy link

Silun commented May 20, 2016

Hello,

for the longest time, Google Play Music has been without any kind of loudness normalization. Many songs are too quit in comparison to others, which is in part due to the loudness war of the past and some recording label's recent departure from it. Especially songs uploaded by oneself are plagued by this issue, and Google themselves have ignored this problem for years.

Loudness normalization, or even better - Replaygain - will fix this issue once and for all, if it can be implemented. AFAIK standard normalization can work on the fly, but is faulty at times. Replaygain will need to quickly scan a song (a matter of mere seconds nowadays) before adjusting the volume. Information on the process can be found on the hydrogenaudio wiki:

http://wiki.hydrogenaud.io/index.php?title=ReplayGain

Implementing the output sound device selection was a great improvement to your software and supplied a much-needed feature that Google Play itself did not provide. Once again, the situation looks grim without your help!

@MarshallOfSound
Copy link
Owner

@Silun This is one of those things that is nice to think of but is rather tricky to implement.

Basic volume normalization can be achieved with a DynamicsCompressorNode

However I don't think this is true "normalization".

The major problem behind any implementation though is that in order to transform the audio it needs to pass through an AudioContext. When it passes through an AudioContext the method we use to change the audio output device setSinkId(id) no longer works and audio is reverted back to the default device.

This is an underlying implementation flaw in Chromium and has prevented the equalizer from being enabled for a long time.

The best i can do for now is mark this has Blocked and wait for Chromium to implement the setSinkId method on AudioContext elements

@MarshallOfSound
Copy link
Owner

For those wondering you can track the sequence of Chromium WebAudio issues over at

https://bugs.chromium.org/p/chromium/issues/detail?id=595635

That is just one of the bugs but it appears to be the one where discussion has happened recently

@SolarLiner
Copy link
Contributor

SolarLiner commented May 22, 2016

@MarshallOfSound Using a compressor is nowhere near normalization. Proper normalization would mean looking through the whole file, detecting the highest peak, and setting it to 0 dBFS. A compressor however, looks through a timeframe, usually through a moving average, and ducks volume past a certain threshold.

As an electronic music producer, I know my way around compressors and limiters, and using a compressor isn't the way to go here. The attack and release parameters would need to be handpicked for each song manually to not completely destroy the track's dynamics, and even then it could still lead to compression artifacts (hearing the sound "pump" on sudden loud noises, for example).
That being said, I do not know what kind of algorithm Chrominium uses for its dynamics compressor, and there are transparent compressing and RMS-triggered algorithms, which greatly help with the artifacts, however there is still the need to tweak the attack and release values for each song.

ReplayGain would be the nice implementation, however it requires analyzing each file to determine its loudness and change the volume according to that. So, it falls back to Google's responsibility to implement such a feature.

@MarshallOfSound
Copy link
Owner

OK, first up thanks @SolarLiner for the in depth explanation of the magic of normalization. I've actually done a lot of research into this over the last few weeks and I basically learnt exactly what @SolarLiner said.

TLDR: True normalization requires some kind of "look ahead" algorithm

Unfortunately due to how GPM works and how it streams audio we can't perform any "look-ahead" analysis of the audio.

I've tried making the audio play at 1000x and then sending it back to the beginning and capturing the waveform but this caused some epic sounds which I shall never play again for my own ear safety.

So as a final thingy.

Yes, it's possible in theory. But no it's not possible in practice. Closing as wontfix

@Barleyman
Copy link

A daft question. If you've got a song list, couldn't you play them ahead to generate volume data?

@jostrander
Copy link
Collaborator

Unfortunately not.

Unfortunately due to how GPM works and how it streams audio we can't perform any "look-ahead" analysis of the audio.

We don't actually have any way of playing future songs without Google playing it in the player.

@eykamp
Copy link

eykamp commented Apr 24, 2017

With ReplayGain, there is no need for lookahead -- all the analysis is done ahead of time and the results are stored in the music file itself. The player just needs to read the computed values and adjust the volume accordingly.

@griest024
Copy link

@eykamp So then wouldn't you have to reupload every single song to Google so the file on the server contains the data needed by ReplayGain?

@SolarLiner
Copy link
Contributor

I believe Google processed the sent tracks for cataloging and other purposes - stripping unnecessary data along the way. Even if you passed your entire catalog for ReplayGain - EBU normalization, you would still not get the ReplayGain data - and All Access users can't even do it anyway.

@Barleyman
Copy link

Actually majority of your songs will not be uploaded at all. The upload app generates a hash and then you get a matching song from Google library when you play it. Even worse, if you try to be sneaky and recompress the song with normalization applied it STILL gets replaced by the standard version from the library. I guess theoretically you could complain about individual songs being too quiet but that's about it.

@griest024
Copy link

So clearly that it not the way to go, but if we could get ReplayGain to store results in a local file, normalization could theoretically be achieved? The only problem in that case is how to generate those results. I can imagine 3 possibilities:

  1. Generate the data from local versions of your music. This is good for people like me that have local versions of all music. However this doesn't help for people that don't have local versions and it doesn't help for radio. Plus, there is the problem of trying to find the correct volume data for the streaming song once its been generated from local files. I dunno how easy that would be exactly.

  2. Generate data from a stream. Obviously you would have to stream the song at least once before you could normalize, but that wouldn't bother me too much. Judging by the previous comments, this looks to be a tricky hack.

  3. Use google play's download feature to download the actual music file and generate it from that. I don't know if this has been implemented yet, but seeing as its present on the web app, it shouldn't be too bad. Presumably (correct me if I'm wrong), the file downloaded is identical to the one in Google's library (and therefore the one you stream), and not necessarily the one you uploaded so it should be easy to match generated data.

Personally 3 seems like the best option to me. Of course, this entire discussion would be moot if Google would normalize all their versions of the songs but if they haven't done it yet, I doubt they will. I've encountered songs on the same album that have wildly different equalizations though, so it is really Google's fault.

@SolarLiner
Copy link
Contributor

You can only ever download a single song twice. However you can download the entire catalog as often as you like.

But this only applies to user-uploaded music. All Access tracks and radios can't profit from solution 3.

@griest024
Copy link

I'm not familiar with ReplayGain, does it always generate the same data for each file? Could we maintain a community version of the generated volume data (lets call it volume-data.json) for the Google library?

@eykamp
Copy link

eykamp commented May 20, 2017 via email

@griest024
Copy link

well the benefit of generating volume-data.json from the Google version of the song is that it should be easy to match it later when streaming because the file is identical.

I should rephrase my previous comment. If we were to have a community volume-data.json it would be hard to decide what options to use while generating it. Is it possible to generate a "master file" that holds all the data needed to satisfy all, or at least most, of the options? So each user can decide exactly how the volume normalizer uses volume-data.json.

@eykamp
Copy link

eykamp commented May 20, 2017 via email

@griest024
Copy link

We have to consider that some songs are simply meant to be louder than others. Especially when you consider the larger range of audio than this feature could be applied to: spoken word etc.

From wikipedia:

ReplayGain analysis can be performed on individual tracks, so that all tracks will be of equal volume on playback. Analysis can also be performed on a per-album basis. In album-gain analysis an additional peak-value and gain-value, which will be shared by the whole album, is calculated. Using the album-gain values during playback will preserve the volume differences among tracks on an album.

On playback, listeners may decide if they want all tracks to sound equally loud or if they want all albums to sound equally loud with different tracks having different loudness. In album-gain mode, when album-gain data is missing, players should use track-gain data instead.

It looks as though ReplayGain has this covered; loudness is decided at playback, rather than at analysis. Am I understanding that correctly?

I am fine with the default settings, at least for now. The feature can always be improved later and something is better than nothing.

@SolarLiner
Copy link
Contributor

ReplayGain is never processed at playback because it needs to whole track at once to define a loudness value. It simply can't be used on this application unless Google implants it.

There are other techniques like auto gain staging which are used in real time mixing.

Maybe something could be done with EBU128 specifications which have real-time implementations.

@griest024
Copy link

How feasible is it to generate extra data so that a user could use either track or album-based normalization at playback?

@SolarLiner
Copy link
Contributor

EBU128 is a kinda of ReplayGain successor for broadcasting: the idea is the same, the specifics are different but the goal is to level out differences between programs on radio and TV. It is also used for live broadcasting, so I think something can be leveraged from that. Doing so would require no pre-processing and no extra metadata, however I'm pretty sure it won't sound as natural.

@eykamp
Copy link

eykamp commented May 21, 2017 via email

@griest024
Copy link

The proof of concept must come first and for that, all default settings and track-based normalization is perfectly fine.

Google needs to implement this, its only adding metadata for the file, its not like the audio data itself is changed at all. And they wouldn't even have to add it as metadata, the volume data could be served through a separate API call.

@ceryen
Copy link

ceryen commented Aug 27, 2017

This issue has been long closed already, so I don't know if anyone will see this comment, but I'm not sure where else to put this comment =P

I have an idea for an implementation. What if GPMDP maintains its own database of ReplayGain values? For a song that doesn't have a ReplayGain value, the first time you completely play through that song, GDMDP could calculate the song's ReplayGain value and store it in GPMDP's database of ReplayGain values. So the first playthrough of a song would not have any normalization, but subsequent playthroughs would benefit from the ReplayGain value calculated during the first playthrough. Your music library would slowly and eventually become normalized, with the set of music you listen to most frequently becoming normalized most quickly.

I can imagine that this might be non-trivial to implement, so I would understand if the idea is rejected =P

@griest024
Copy link

@ceryen I suggested this earlier in this thread:

Could we maintain a community version of the generated volume data

@ceryen
Copy link

ceryen commented Aug 27, 2017

@griest024 Sorry, I missed that you already expressed the idea of generating ReplayGain values after a track has been played through once. I would like to also say that it wouldn't bother me either that the first playthrough wouldn't have normalization.

Having a community-generated database of ReplayGain values is tricky though. The database would be fairly large since there is quite a lot of music available on Google Play Music. It would require much more infrastructure and resources from MarshallOfSound, he would need to pay for that database to be hosted somewhere. A locally generated and maintained database might be more appealing to MarshallOfSound since it wouldn't require extra infrastructure, only resources on the user's computer.

@Barleyman
Copy link

Barleyman commented Aug 27, 2017 via email

@eykamp
Copy link

eykamp commented Aug 27, 2017 via email

@ceryen
Copy link

ceryen commented Aug 27, 2017

I'm not sure using a song fingerprint would be possible if you have to be able to identify the song before it even starts playing. There are also 40 million songs in Google Play Music.

The size of the database was more of an ancillary point. Even if the database is not very large, it needs to be hosted somewhere that is accessible to all users and hosted in a way such that user clients can submit updates. That will have some hosting costs. There is also development costs in terms of setting that infrastructure up. It would be up to MarshallOfSound to decide whether those costs would be worth it. My only point is that a locally generated database would avoid those costs without significant detriment to the user.

Another challenge with a global database is that it can get polluted with music that people have themselves uploaded to Google Play Music. You would need to filter those user-uploaded songs out or else the database would be polluted with music that most people cannot even access.

@griest024
Copy link

griest024 commented Aug 27, 2017

Even if the database is not very large, it needs to be hosted somewhere that is accessible to all users and hosted in a way such that user clients can submit updates

Uh..github? LOOT does something similar.

Edit: @ceryen for the record, I think a locally generated version of the file is fine but a community version wouldn't require the song to be played through once first. As for the size issue, it could possibly get quite large but I doubt that data would end up being generated for even 10% of the play database.

@ceryen
Copy link

ceryen commented Aug 27, 2017

GitHub does not allow files larger than 100MB to be checked in. GitHub does have GIT LFS, which will allow larger files, but with the restriction of 1GB of free storage and only 1GB of bandwidth per month.

Furthermore, using Git to store binary files is a terrible idea, it will cause your repository size to explode. To quote GitHub: "If you push a 500 MB file to Git LFS, you'll use 500 MB of your allotted storage and none of your bandwidth. If you make a 1 byte change and push the file again, you'll use another 500 MB of storage and no bandwidth, bringing your total usage for these two pushes to 1 GB of storage and zero bandwidth."

LOOT does something similar.

Their file is 788KB, nowhere near the same magnitude in size.

@griest024
Copy link

griest024 commented Aug 27, 2017

Furthermore, using Git to store binary files is a terrible idea

I thought ReplayGain can store data in json format (at least mp3gain can).

GitHub does not allow files larger than 100MB to be checked in.

Fair enough, use gitlab.

@ceryen
Copy link

ceryen commented Aug 27, 2017

I thought ReplayGain stores data in json format.

Then you're talking about more than 8 bits per song for ReplayGain, although I don't see why GPMDP would need to store things in JSON, it could just store the bare value.

But fair enough, let's say the file is text rather than binary.

Fair enough, use gitlab.

If you do store the database in GitHub/GitLab, what is the plan for receiving updates from users? Make them register GitHub/GitLab accounts and submit pull requests? Seems more annoying than just adjusting the playback volume by hand.

@Barleyman
Copy link

Barleyman commented Aug 27, 2017 via email

@griest024
Copy link

So a simple exercise becomes much more convoluted as you'd have to
intercept the player audio stream and adjust/analyze it on the fly.

It seems like adjusting the volume wouldn't be too difficult, but getting enough data to actually do a replaygain analysis might be tricky; it would probably require writing our own implementation of replaygain.

@skris88
Copy link

skris88 commented Dec 5, 2018

Google Play Music and Android Auto is a match made in Heaven.

But it appears Google sometimes uses it's own library files and sometimes the file I uploaded.

Because of volume variations, I deleted all my Google Play Music personal library uploads, and ran Replay Gain on all my files, then uploaded them again (yes, it took a LONG time).

I can play an album and my preset replay gain set volume of -10dBFS plays fine (I like to leave a bit of headroom as playback sounds better on lower quality DACs). Then the occasional 0dBFS track plays - which must be from Google's own copy of the file. Blasting through the only ear drums I have and will ever have. Or worse, a file someone else compressed to +-0dB dynamic range and uploaded at 0dbFS (it'll be like some 20dB louder).

Arrrrrrrrrr!!

If I can Replay Gain all my files on my crap home PC, Google you can automatically do so for anything being uploaded. And reduce space by 'sharing' files so only 1 copy of a file need be on your servers. A simple switch to have tracks replayed in Track mode or Album mode is all it takes to keep audiophile purists happy. And hey, while you are at it, have an option to playback the file in full dynamic range or compressed as some listeners like it. Hey, a $30 DVD player from a supermarket has the ability (some call it Night mode and Normal mode), and Google Play doesn't??

Common Google, you can do better than this. Do it NOW!

@SolarLiner
Copy link
Contributor

SolarLiner commented Dec 5, 2018 via email

@skris88
Copy link

skris88 commented Dec 7, 2018

Nice. But not everyone can cannot afford to pay for YouTube Music without adverts.

If Google can legally play a track on my Google Play Music downloads that is clearly not the track I uploaded, they can offer the option to use the ReplayGain metadata already in the files we uploaded.

@jostrander jostrander mentioned this issue Jan 14, 2019
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants