I made a rudimentary effect synthesizer and sound manager. It's convenient for arcade type games and such. The sound is deliberately a bit distorted, for a little retro vibe.
main.cpp
#include <SFML/System.hpp>
#include "soundMan.hpp"
int main(int argc, char** argv)
{
SoundMan* sm = new SoundMan();
int boom = sm->createNoise( 80000, 0.4f, 0.1f, true);
int bam = sm->createNoise( 15000, 1.0f, 1.0f, true);
int zap = sm->createNoise( 5000, 0.0f, 1.0f, false);
int pew = sm->createBeep( 5000, 2000.0f, 50.0f, 0.0f, 0.0f, true);
int alien1 = sm->createBeep( 100000, 2000.0f, 50.0f, 0.5f, 0.9f, true);
int alien2 = sm->createBeep( 100000, 20.0f, 1500.0f, 1.0f, 1.0f, true);
int bigFail = sm->createBeep( 100000, 500.0f, 50.0f, 0.1f, 0.4f, true);
sm->playSound(boom);
sf::Sleep(0.5f);
sm->playSound(bam);
sf::Sleep(0.5f);
sm->playSound(zap);
sf::Sleep(0.5f);
sm->playSound(pew);
sf::Sleep(0.5f);
sm->playSound(alien1);
sf::Sleep(0.5f);
sm->playSound(alien2);
sf::Sleep(0.5f);
sm->playSound(bigFail);
return 0;
}
soundMan.hpp
#pragma once
#include <vector>
#include <cmath>
#include <cstdio>
#include <SFML/Audio.hpp>
class SoundMan
{
private:
std::vector<sf::Sound*> playerVec;
std::vector<sf::SoundBuffer*> soundBufVec;
unsigned int currentPlayer;
inline float symClip(float Value, float Limit = 1.0f)
{
return ((fabsf(Value+Limit) - fabsf(Value-Limit)) * 0.5f);
}
public:
SoundMan();
~SoundMan();
void playSound(int index);
//assumes SR = 44100
//Frequencies given in Hz, for example start at 1000.0, end at 100
//Wobble is pitch modulation. Both depth and rate are in the 0.0 to 1.0 range
//A wobble depth of 0.0f turns it off.
int createBeep( int lengthInSamples, float startFrequency, float endFrequency,
float wobbleRate, float wobbleDepth, bool fadeOut);
//Lowpass parameters are in the 0.0 to 1.0 range. 1.0 means the filter is fully open.
int createNoise( int lengthInSamples, float lowPassStart, float lowPassEnd, bool fadeOut);
};
soundMan.cpp
#include "soundMan.hpp"
SoundMan::SoundMan()
{
playerVec.push_back( new sf::Sound() );
playerVec.push_back( new sf::Sound() );
playerVec.push_back( new sf::Sound() );
playerVec.push_back( new sf::Sound() );
playerVec.push_back( new sf::Sound() );
currentPlayer = 0;
}
SoundMan::~SoundMan()
{
while(!playerVec.empty())
{
delete playerVec.back();
playerVec.pop_back();
}
while(!soundBufVec.empty())
{
delete soundBufVec.back();
soundBufVec.pop_back();
}
playerVec.clear();
soundBufVec.clear();
}
void SoundMan::playSound(int index)
{
playerVec[currentPlayer]->Stop();
playerVec[currentPlayer]->SetBuffer( *(soundBufVec[index]) );
playerVec[currentPlayer]->Play();
currentPlayer++;
if(currentPlayer == playerVec.size()) currentPlayer = 0;
}
int SoundMan::createBeep( int lengthInSamples, float startFrequency, float endFrequency, float wobbleRate, float wobbleDepth, bool fadeOut)
{
sf::Int16 preBuffer[lengthInSamples];
const float p1 = startFrequency / 44100.0f;
const float p2 = endFrequency / 44100.0f;
float phase = 0.0f;
float wobPhase = 0.0f;
for(int i = 0; i < lengthInSamples; i++)
{
const float alpha = (float)i / (float)lengthInSamples;
const float p = p1 + alpha * (p2 - p1);
phase +=p;
if(phase > 1.0f) phase -= 1.0f;
wobPhase += (wobbleRate * 0.001f);
if(wobPhase > 1.0f) wobPhase -= 1.0f;
const float wob = sin( 2.0 * M_PI * wobPhase);
float tmp = sin( 2.0 * M_PI * (phase + wob * wobbleDepth));
tmp=tmp*tmp*tmp;
tmp = symClip(tmp, 0.6f);
if(fadeOut)
{
const float vol = 1.0f + alpha * -1.0f;
tmp = tmp * vol * vol;
}
preBuffer[i] = sf::Int16(tmp * 32767);
}
sf::SoundBuffer* sBuf = new sf::SoundBuffer();
sBuf->LoadFromSamples(preBuffer, lengthInSamples, 1, 44100);
soundBufVec.push_back(sBuf);
return soundBufVec.size() - 1;
}
int SoundMan::createNoise( int lengthInSamples, float lowPassStart, float lowPassEnd, bool fadeOut)
{
float buf1 = 0.0f;
float buf2 = 0.0f;
const float F1 = lowPassStart * 0.7f;
const float F2 = lowPassEnd * 0.7f;
sf::Int16 preBuffer[lengthInSamples];
for(int i = 0; i < lengthInSamples; i++)
{
float tmp = sf::Randomizer::Random(-0.9f, 0.9f);
const float alpha = (float)i / (float)lengthInSamples;
float F = F1 + alpha * (F2 - F1);
F = F * F * F;
buf1 += F * (tmp - buf1);
buf2 += F * (buf1 - buf2);
tmp = buf2;
tmp = tmp * (1.0f / F);
tmp = symClip(tmp, 0.6f);
if(fadeOut)
{
const float vol = 1.0f + alpha * -1.0f;
tmp = tmp * vol * vol;
}
preBuffer[i] = tmp * 32767;
}
sf::SoundBuffer* sBuf = new sf::SoundBuffer();
sBuf->LoadFromSamples(preBuffer, lengthInSamples, 1, 44100);
soundBufVec.push_back(sBuf);
return soundBufVec.size() - 1;
}