Simple sound wave generator with SDL in c++

前端 未结 4 596
孤城傲影
孤城傲影 2020-12-13 22:36

i am having problems understanding how the audio part of the sdl library works now, i know that when you initialize it, you have to specify the frequency and a >>callback<

4条回答
  •  眼角桃花
    2020-12-13 23:05

    The Introduction to SDL (2011 cached version: 2) has got a neat example of using SDL Sound library that should get you started: http://www.libsdl.org/intro.en/usingsound.html

    EDIT: Here is a working program that does what you asked for. I modified a bit the code found here: http://www.dgames.org/beep-sound-with-sdl/

    #include 
    #include 
    #include 
    #include 
    
    const int AMPLITUDE = 28000;
    const int FREQUENCY = 44100;
    
    struct BeepObject
    {
        double freq;
        int samplesLeft;
    };
    
    class Beeper
    {
    private:
        double v;
        std::queue beeps;
    public:
        Beeper();
        ~Beeper();
        void beep(double freq, int duration);
        void generateSamples(Sint16 *stream, int length);
        void wait();
    };
    
    void audio_callback(void*, Uint8*, int);
    
    Beeper::Beeper()
    {
        SDL_AudioSpec desiredSpec;
    
        desiredSpec.freq = FREQUENCY;
        desiredSpec.format = AUDIO_S16SYS;
        desiredSpec.channels = 1;
        desiredSpec.samples = 2048;
        desiredSpec.callback = audio_callback;
        desiredSpec.userdata = this;
    
        SDL_AudioSpec obtainedSpec;
    
        // you might want to look for errors here
        SDL_OpenAudio(&desiredSpec, &obtainedSpec);
    
        // start play audio
        SDL_PauseAudio(0);
    }
    
    Beeper::~Beeper()
    {
        SDL_CloseAudio();
    }
    
    void Beeper::generateSamples(Sint16 *stream, int length)
    {
        int i = 0;
        while (i < length) {
    
            if (beeps.empty()) {
                while (i < length) {
                    stream[i] = 0;
                    i++;
                }
                return;
            }
            BeepObject& bo = beeps.front();
    
            int samplesToDo = std::min(i + bo.samplesLeft, length);
            bo.samplesLeft -= samplesToDo - i;
    
            while (i < samplesToDo) {
                stream[i] = AMPLITUDE * std::sin(v * 2 * M_PI / FREQUENCY);
                i++;
                v += bo.freq;
            }
    
            if (bo.samplesLeft == 0) {
                beeps.pop();
            }
        }
    }
    
    void Beeper::beep(double freq, int duration)
    {
        BeepObject bo;
        bo.freq = freq;
        bo.samplesLeft = duration * FREQUENCY / 1000;
    
        SDL_LockAudio();
        beeps.push(bo);
        SDL_UnlockAudio();
    }
    
    void Beeper::wait()
    {
        int size;
        do {
            SDL_Delay(20);
            SDL_LockAudio();
            size = beeps.size();
            SDL_UnlockAudio();
        } while (size > 0);
    
    }
    
    void audio_callback(void *_beeper, Uint8 *_stream, int _length)
    {
        Sint16 *stream = (Sint16*) _stream;
        int length = _length / 2;
        Beeper* beeper = (Beeper*) _beeper;
    
        beeper->generateSamples(stream, length);
    }
    
    int main(int argc, char* argv[])
    {
        SDL_Init(SDL_INIT_AUDIO);
    
        int duration = 1000;
        double Hz = 440;
    
        Beeper b;
        b.beep(Hz, duration);
        b.wait();
    
        return 0;
    }
    

    Good luck.

提交回复
热议问题