Changing Pitch/Frequency of .wav Files

Hello There,

Is there a way to load a .wav file into C++, run through a for-loop or while-loop, and within each cycle of the loop, change the frequency/pitch sound of the .wav file very slightly and save each change as a newly created .wav file. So basically I want to take my original .wav and make about 300 copies each with a slight increase in pitch/frequency sound.

Thanks, Gary.
Yes all of that is possible.

Loading a wav can be done manually if you know the .wav file format, though it's probably easier to use an audio lib to load the files for you. I'm pretty sure BASS and FMOD can save/load wav files and probably can give you access to the wav data. BASS is probably easier to use for beginners.

As for changing the frequency, there's 2 general ways to do this.

1) Change the samplerate -- this is pretty easy to do and will accomplish the goal, but will have the side-effect of changing how long the wav plays. IE, if you have a wav that plays for 3 seconds, and you change it to play an octave lower, it will instead play for 6 seconds (think of an old tape recorder with batteries dying -- it is slower, but lower pitch.... and the opposite would be faster but higher pitch)

2) Run the audio through an FFT (google FFT / Fast Fourier Transform for some libs) in blocks, adjust the pitch of each block, then run through an inverse FFT, and mix all the blocks back together. This is significantly more complicated but will allow you to change the pitch without changing the runtime of the audio.
Thanks for the links, Disch, the back of my mind had been interested in programmatically creating audio as well.
If you want a relatively simple but incredibly fun project to generate audio from scratch... I recommend making an NSF player.

NSF files are the music data extracted from NES Roms. So they effectively have the full soundtrack to Nintendo games in a very small file. Super super fun. =)
I haven't toyed around with audio in many years, but don't most modern sound cards have hardware that can do the FFT in real time during playback? This would save you the need to store 300 copies of the .wav.
Thank you Disch.

I've had a look at BASS on the Un4seen website. So then it seems I would need to download BASS and link it into Visual C++ 2010 Express correctly (the compiler I'm using), which would probably be a challenge for me (although I've managed to link Allegro 5 correctly, but there were lots of examples, so hopefully there would be for BASS as well). Also I managed to stumble across the documentation in the "Other Stuff" section right at the bottom of their page, but for me it's definitely looking very complicated/advanced and so I would have to somehow find a way to understand how to get into using it.

Here's how I used to do it in Python below, but even though I already have my several hundred .wav files, I don't want to have to distribute them with my game as they add up to about 75MB, whereas the .exe and the images altogether only total about 6MB. This method below in Python works perfectly.

EDIT: Once the files are created I then load all of them using Allegro's sound functions. After doing this, I could even delete them (which I've tried and the .wav sounds just carry on playing :) ). I know this is crude but it works. Allegro cannot manipulate the frequency in the simple way Python can, well at least I don't think so anyway.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import wave    # THIS IS Python Code, NOT C++ #

pitch = 44100

for x in range(1000):
 
    f = wave.open ('MunchEatPill3.wav')
    # read in entire wav file
    nFrames = f.getnframes()
    wdata = f.readframes(nFrames) 
    params = f.getparams()
    #print(wdata)
    #print(params)
     
    f.close()

     
    n = list(params)
    
    n[0] = 2 # Mono = 1 Sterio = 2
    
    n[2] = pitch

    pitch += 50
     
    params = tuple(n)

    name = 'MunchEatPill3C++' + str(x) + '.wav'     
     
    f = wave.open(name, 'wb')
    f.setparams(params)
    print(params)
    f.writeframes(wdata)
    f.close()
Last edited on
SFML also has some basic audio facilities. Might be easier to get started with than BASS.

http://sfml-dev.org/index.php
Thanks I'll take a look :)
SFML likely can load wav files but I don't know if it's able to save them.
I've managed to compress my initial 72KB .wav file down to 4.65KB, and reduce the number of them from 1000 to 450. So the total memory for my hundreds of .wav files is now only about 2MB, whereas before it was 72MB.

So thank you all for your advice and links to the various libraries, which I hope one day I'll be able to understand.

I'll mark this thread as solved.
Last edited on
Have you considered using mp3/ogg vorbis instead of wav?

Ogg Vorbis is like mp3, only generally superior and unbound by license restrictions. SFML supports ogg playback out of the box.
Thank you once again. That's something else for me to consider.
Topic archived. No new replies allowed.