Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: Way to change the playback sampling rate without resampling? (Read 3681 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

Way to change the playback sampling rate without resampling?

Most of the music found in Nintendo 64 games use slightly off-standard sampling rates, like 22047Hz and 32006Hz.  There are some other N64 games that use other oddball sampling rates that aren't too too far off more standard rates like 24000Hz, but they're such seemingly random sampling rates that I cannot even remember the value off the top of my head (I believe Mario Kart 64 as well as Donkey Kong 64 are two N64 games that used almost random-seeming sampling rates).

Rather than spending CPU cycles (which, at such fractional rates, can actually be quite intensive, especially if combined with interpreter N64 music decoding which is necessary for some USF files), I would much rather just slightly speed up or slow down the audio so as to match the much more standardized sampling rates of 22050Hz, 24000Hz, and 32000Hz, at which point they can then be resampled up to the likes of 44.1KHz, 48KHz, or 96KHz with less CPU overhead due to being an exact multiple and is then directly compatible through your usual WASAPI Exclusive and the like.  Such process could also be useful for conversion and exporting.

This would also work extremely well with a function similar to what the SoX mod resampler DSPs have where differing input sampling rates can be included/excluded from a given target sampling rate (so if the desired target is 22050Hz, I could set it to only apply as such if the input is 22047Hz, and then do the same with a target of 32000Hz if the input is 32006Hz).

Currently I have to do this the manual way by exporting the audio at its native sampling rate directly from a USF to LPCM WAV files, opening them into Audacity, using the function historically labeled as "Set Rate" to set the playback sampling rate of a given audio (so if it was 32006Hz, I set it to 32000Hz) and set the project rate similarly (changing 32006Hz to 32000Hz so as to avoid resampling), exporting as a new WAV file, and then playing back said WAV file(s) in foobar2000.

Re: Way to change the playback sampling rate without resampling?

Reply #1
Rather than spending CPU cycles (which, at such fractional rates, can actually be quite intensive, especially if combined with interpreter N64 music decoding which is necessary for some USF files)
Why care so much about CPU cycles? Unless you have really ancient CPU.

Re: Way to change the playback sampling rate without resampling?

Reply #2
Why care so much about CPU cycles? Unless you have really ancient CPU.
Admittedly I probably would have been better off asking about this around a decade ago when I first started doing the manual process of slightly speeding up and slowing down N64 music...

Nevertheless, I figured that CPU usage was a more legitimate concern than arguing over whether the quality would have any impact at all with regards to resampling since simply adjusting the sampling rate playback is a lossless alteration while resampling isn't. And since it's looking like there are going to be more ARM-based devices on the horizon (particularly with Apple), I thought keeping CPU utilization low could be important with regards to the x86 --to-> ARM translation that can definitely eat up CPU cycles.

(similarly, I don't know if foobar2000 on mobile can use the same DSPs and 3rd party components and stuff, but if it can, then CPU utilization would be very important there for battery life reasons, especially since USF files in the form of miniUSF can have really small file sizes making it perfect for use on mobile devices...assuming that one is not using USF files that need to use the "interpreter" setting which farther eats up CPU cycles)

It did make me think though that this could also be very useful for batch converting/exporting in terms of how long it takes since resampling would be slower than just slightly adjusting the sampling rate.

 

Re: Way to change the playback sampling rate without resampling?

Reply #3
WAV Header Investigator can be used to edit the sampling rate of a group of sound files. This will be faster less prone to mistakes than going through a DAW export.

Re: Way to change the playback sampling rate without resampling?

Reply #4
WAV Header Investigator can be used to edit the sampling rate of a group of sound files. This will be faster less prone to mistakes than going through a DAW export.
That seems to only include specific sampling rates and doesn't let you input a custom one, which is unfortunate because 24000Hz is not one of the listed choices.

But for 22050Hz and 32000Hz that works well to eliminate a few steps, at least in terms of offline conversion.

Technically for sampling rates near to 24KHz I guess one could first upsample by exactly 2x and then use that tool to set the sampling rate to 48000Hz, but that kind of defeats the point if one is trying to do a lossless edit, at which point if CPU power isn't a concern then you might as well just resample directly to 48KHz and call it a day...

Re: Way to change the playback sampling rate without resampling?

Reply #5
Apologies for kind of grave-digging this thread as well as double-posting, but it turns out that the sampling rate, bit depth values, and even the according text labels used in "Header Investigator" are stored completely unencrypted.  This means that one can actually use a basic hex editor to locate the according hex value in little endian format for a given sampling rate, bit depth, or text label and just change them to the desired value, and sure enough it'll all "just work" - even if it's an extremely non-standard value such as a sample rate of 123,456 Hz ("40 E2 01" in little endien hexadecimal).


So using my experience with game mods and since I know that distributing modified EXEs as a bit of a no-no (especially of non-open source software), I put together some patch files that make my desired changes.  Furthermore, the ridiculously tiny sizes of the resulting patch files (no larger than 35 bytes; not a typo) should help to alleviate any security concerns, and even then I've spelled out the changes that each patch makes in case one is more comfortable doing any such hex-editing manually.

Normally I would use bps or xdelta patches, but due to the way I did this, the patches can actually be stacked, combined, and/or mixed and matched in any combination desired, so it was just easier to use IPS format instead which doesn't have a checksum function.

Lastly, I've left the modified listings in the program itself out-of-order (e.g. bit depth listing of 32, 16, 24 rather than the expected 16, 24, 32) because keeping thing in-order would require not only increasing the patch sizes but also would make it more difficult to be able to stack and/or mix and match the patches.  It also makes it much more obvious what has been modified and makes it much simpler to convey the actual hex values that have been edited.


So with all of that out of the way, here are my modification patches for Header Investigator (see attached files):

8000>24KHz.ips - Replace 8,000 Hz sample rate with 24,000 Hz
List of hex changes
Hex address 2f2e: 40 1f--to->c0 5e (detected sample rate: 8000--to->24000 )
Hex address 3343: 40 1f--to->c0 5e (applied sample rate: 8000--to->24000 )
Hex address 26bfc: 38 2c 30--to->32 34 2c (text label: 8,0--to->24, )
Hex address 26c01: 00--to->30 (text label: [blank]--to->0 )

11025>176.4KHz.ips - Replace 11,025 Hz sample rate with 176,400 Hz (auto-detection of 176,400 does not work, so you need to manually select 176,400)
List of hex changes
Hex address 2f37: 11 2b 00--to->10 b1 02 (detected sample rate: 11025--to->176400 but it doesn't function...)
Hex address 334c: 11 2b 00--to->10 b1 02 (applied sample rate: 11025--to->176400 )
Hex address 26bf5: 31 2c 30 32 35 00--to->37 36 2c 34 30 30 (text label: 11,025--to->176,400 )

8>32bit.ips - Replace 8 bit depth resolution with 32 bit (even works with 32 bit floating point)
List of hex changes
Hex address 3113: 08--to->20 (detected bit depth: 8--to->32 )
Hex address 33ef: 08--to->20 (applied bit depth: 8--to->32 )
Hex address 26ba8: 38 00--to->33 32 (text label: 8--to->32 )

If you don't know how to apply IPS files then the easiest way is probably via http://www.marcrobledo.com/RomPatcher.js/ - for "ROM file" select the original unmodified Header Investigator EXE, then for "Patch file" select one of the desired IPS files.  If you'd prefer using an offline patcher, I personally use "Floating IPS" aka "Flips" - https://github.com/Alcaro/Flips



Reference information for geeks that know what they're doing
Within the program, there are two values for each given sampling rate and bit depth - the detected value of the existing WAV file, and the value to actually apply to the WAV file.  The text labels however only have a single value to modify (the only reason I have two listings for the text label on the 8000>24KHz patch is because the two ending zeros of "8,000" were left unmodified but I still then needed a third zero because the initial 0 of 8,000 was turned into a comma considering that the 8  was changed to 2 and the comma was changed to 4, and with a basic hex edit the text label had to start at the same hex address that the 8 was located at or else it wouldn't display properly in Header Investigator).

For the sampling rates and bit depths, you can find out what the according hex value is right in the Windows calculator if you switch it to "Scientific" mode - select 'Dec", type in an according demical value, and then select "Hex".  That'll give the value in big endien though, so you'll need to reverse each 2-sets of digits around to make it little endien.  For example, if you put in the decimal value 176400 and then switch to hex, it'll give you the value "2 b1 10" without spaces, so in little endien hexadecimal that value is "10 b1 02".

For the text labels, that stuff can be found by just saving a plain .txt file containing whatever characters and opening it in a hex viewer (for example the character" 0 written as "30" in hex, and a comma is written as "2c" in hex)...or you can just refer the value under "Hx" for a given character on the following cheat-sheet - https://archive.is/v6qIr

Re: Way to change the playback sampling rate without resampling?

Reply #6
Another apology for triple-posting, but somehow I typo'd every instance of the hexadecimal value for 24000 - it's supposed to be "c0 5d" in little endien, not "c0 5e" (which itself actually refers to 24256).

It's now been too long for me to be able to edit the post, but at least the actual attached IPS patch files contain the correct values.