Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A small code to change a sfx frequency with SDL_mixer.
//Danilo Lemos - 2017
//change_frequency.c
//======================
//A small function to play a SDL_mixer's chunk in a different frequency.
//It was written to be used on the Pekka Kana 2 SDL2 game project, and is free to use and edit.
#include <SDL2/SDL_mixer.h>
#include <stdio.h>
#define MIX_CHANNELS 8 //Number of channels used
#define PLAY_FREQUENCY 44100 //Frequency that SDL_mixer will work
Mix_Chunk* sample_chunk;
Uint8* freq_chunks[MIX_CHANNELS]; //The new chunk allocated for each channel
int Change_Frequency(Mix_Chunk* chunk, int freq){
int channel;
SDL_AudioCVT cvt;
SDL_BuildAudioCVT(&cvt, MIX_DEFAULT_FORMAT, 2, freq, MIX_DEFAULT_FORMAT, 2, PLAY_FREQUENCY); //Create a converter from the PLAY_FREQUENCY to "freq"
if (cvt.needed) { //If need to convert
for(channel=0; channel<MIX_CHANNELS; channel++)
if(!Mix_Playing(channel)) break; //Find a free channel
if(channel == MIX_CHANNELS) return -1; //If there is no channel return -1
//Set converter lenght and buffer
cvt.len = chunk->alen;
cvt.buf = (Uint8*)SDL_malloc(cvt.len * cvt.len_mult);
if (cvt.buf == NULL) return -1;
//Copy the Mix_Chunk data to the new chunk and make the conversion
SDL_memcpy(cvt.buf, chunk->abuf, chunk->alen);
if(SDL_ConvertAudio(&cvt) < 0){
SDL_free(cvt.buf);
return -1;
}
//If it was sucessfull put it on the original Mix_Chunk
chunk->abuf = cvt.buf;
chunk->alen = cvt.len_cvt;
//If there was a chunk in this channel delete it
if(freq_chunks[channel] != NULL) SDL_free(freq_chunks[channel]);
//Save the allocated chunk addrass to be deleted some time -- delete it while playing will give SEGFALT
freq_chunks[channel] = cvt.buf;
return channel;
}
else return -1;
}
int play(Mix_Chunk* chunk, int volume, int freq){
if(chunk == NULL) return -1;
chunk->volume = volume;
//Save a backup of the parameter that will be ovewrited
Uint8* bkp_buf = chunk->abuf;
Uint32 bkp_len = chunk->alen;
int channel = Change_Frequency(chunk, freq);
if(channel != -2) //If it was sucessfull
Mix_PlayChannel(channel, chunk, 0); //Play allocated chunk
//Restore the backup
chunk->abuf = bkp_buf;
chunk->alen = bkp_len;
return channel;
}
//This function clean all allocated chunks that isn't playing
int clean(){
for(int i=0;i<MIX_CHANNELS;i++) //Check for each channel
if(!Mix_Playing(i) && freq_chunks[i] != NULL){ //If it was allocated a chunk and it isn't playing
SDL_free(freq_chunks[i]); //Then delete it
freq_chunks[i] = NULL;
}
return 0;
}
//A main function to test the code
int main( int argc, const char* argv[] ){
int channel;
int arg_freq;
if(argc != 3) {
printf("Usage:\n./a.out sound freq\n");
return -1;
}
Mix_OpenAudio(PLAY_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 4096);
sample_chunk = Mix_LoadWAV(argv[1]);
sscanf(argv[2], "%i", &arg_freq);
channel = play(sample_chunk, 100, arg_freq);
while(Mix_Playing(channel));
clean();
Mix_FreeChunk(sample_chunk);
Mix_CloseAudio();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.