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 - 2020
//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 <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) {
Uint16 format;
int channels;
Mix_QuerySpec(NULL, &format, &channels);
int channel;
SDL_AudioCVT cvt;
//Create a converter from the PLAY_FREQUENCY to "freq"
SDL_BuildAudioCVT(&cvt, format, channels, freq, format, channels, PLAY_FREQUENCY);
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]);
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;
}
void channelDone(int channel) {
Uint8* pointer = freq_chunks[channel];
freq_chunks[channel] = NULL;
SDL_free(pointer);
}
//A main function to test the code
int main(int argc, 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, 1024);
Mix_AllocateChannels(MIX_CHANNELS);
Mix_ChannelFinished(channelDone);
sample_chunk = Mix_LoadWAV(argv[1]);
sscanf(argv[2], "%i", &arg_freq);
channel = play(sample_chunk, 100, arg_freq);
while(Mix_Playing(channel));
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.