Ping’ informed me that there are songs that appear to play slower in PyWright than they should. Here is the reason:
In a typical music player, it is always only playing one music/sound at a time. Because of this, it can shape the music player to fit the rate of whatever is loaded. Music can have different sample rates, which is similar to a framerate. It says how many samples per second are stored in the file. When your music player loads a file, it adjust it’s playing rate based on what rate the file says.
Now, with a game engine, it’s not so simple. You have many sound effects and different music playing at different times. Because of the way the hardware works, you can only run things at one speed at a time. If you try to play music stored at one rate, and a sound effect stored at another rate, you either have to stop the music to change the settings and play the sound; or resample each file to the settings of the hardware. Resampling means analyzing the sound file and either cutting out frames to make it a slower rate, or adding frames to make it a higher rate.
Some kinds of resampling are very easy. To double the rate, you just have to read two frames at a time; while to half the rate, you can skip a frame. If you are not doubling or halving the frame rate of the sound though, you have to do deeper analysis of the frames.
The libraries PyWright depends on, namely SDL_Mixer, can do the cheap resampling for free. It doesn’t know anything about more advanced resampling however.
When you check the PyWright sound settings, there are a couple different sample formats to choose. These are all compatible with each other because they are either half or double the frame rate of the next one. If the sample rate of 22050 is chosen, and you try to play a sound that has a sample size of 11025, it will convert that sound into a rate of 22050 in real time, and sound the same as it is supposed to. If you play a sound that is set to 44100 Hz, it will convert it down, and play at the right speed.
Where things get interesting, is if you try to play music that is set at a Hz that can’t be double or halved from the system rate. Most common is 48000. 48000 hz doesn’t half or double to any of the values the system is set to by PyWright. So what happens, is it just pretends that the framerate of that 48000 file is 44100 (if 44100 is your setting). If you change the settings down to 11025, I’m not positive, but I think it does a simple resample down to 12000 (48000/2/2), and then treats it like it is 11025.
How to solve this? If there were an option for it, you could actually set the sound player to have a framerate of 48000, just like the music file you are trying to play. There is just one problem – all of the standard PyWright sounds have a framerate of 44100 or 22050. If you change the settings to match the music, all of the sounds will now sound like they are on helium!
One way to solve this in code, would be to have a smart resampler that resamples the music if it sees that the rate doesn’t fit. This would add two things that I don’t like: much longer loading time for music files as it reads the entire file to convert it; and also making the PyWright installation bigger and harder to package. So I am not going to do this
SOLUTION
Resample your files to either 22050 or 44100. Yes, not only do you have to make sure to use .ogg and not .mp3, you also have to be aware of the sample rate. Such is game development! Of course the other solution is to just let the music play that 20% slower. It’s most likely not that noticeable to most people.
If you are going to resample, make sure to use as your source track the oldest version of the track. If you have an mp3 file, which you converted to ogg, don’t do anything to the ogg. Resample the mp3 and export to ogg in one step if you can. Each operation to a sound file will have some quality lost. wav->mp3 has loss, mp3->ogg has loss, ogg->resample has loss. wav->resample/ogg will have the best outcome.
Here’s how to change the rate in audacity:
Open audacity
Drag source file (wav, mp3, ogg if you have to – use the best quality source you can) into audacity
EDIT: Change the project sample rate in the lower left corner (previously I thought you change sample rate on track itself, but that was wrong)
Click file, export as ogg vorbis, and name the output
Most other converters will also have a field letting you input what you want the output quality to be. They may be like “cd quality”, “better than cd quality” etc. You usually will want cd quality or 44100.
Hope this helps!
