使用SFML生成和播放正弦波时的静态和嗡嗡声

时间:2018-09-26 01:47:49

标签: c++ audio sfml sine synthesizer

我正在编写一个程序,该程序需要快速连续播放许多合成的正弦波。我正在使用C ++和SFML编写此程序。我创建了一个类来代表合成器。它负责产生正弦波并将其播放为单个音频流。但是,每当我使用该应用程序时,都会听到很多crack啪声和爆裂声混杂在一起。我不确定这是否是库问题,还是我产生并输入了错误的正弦波。这是我的代码:

synth.h

#pragma once

#include <SFML/Audio.hpp>
#include <vector>
#include <mutex>

class Synth : public sf::SoundStream {
    std::vector<sf::Int16> m_AudioData;
    std::mutex m_Lock;

    bool m_ClearData, m_Loaded, m_Started;

    int m_Amplitude;

    const float TAU = 6.28318;

public:
    Synth(int);
    Synth(const Synth&);

    ~Synth();

    bool onGetData(sf::SoundStream::Chunk&) override;
    void onSeek(sf::Time) override;

    void makeSound(float, int);
    bool busy();
};

synth.cpp

#include "synth.h"

Synth::Synth(int amplitude)
    : m_Amplitude(amplitude)
    , m_Loaded(false)
    , m_ClearData(false)
    , m_Started(false)
{
    initialize(1, 44100);
}

Synth::Synth(const Synth& other)
    : m_Amplitude(other.m_Amplitude)
    , m_Loaded(false)
    , m_ClearData(false)
    , m_Started(false)
{
    initialize(1, 44100);
}

Synth::~Synth() {
    stop();
}

bool Synth::onGetData(Chunk &chunk) {
    static const sf::Int16 empty[10] = { 0 };

    m_Lock.lock();

    if (m_Loaded) {
        chunk.sampleCount = m_AudioData.size();
        chunk.samples = m_AudioData.data();

        m_ClearData = true;
        m_Loaded = false;
    }
    else {
        if (m_ClearData) {
            m_AudioData.clear();
            m_ClearData = false;
        }

        chunk.sampleCount = 10;
        chunk.samples = empty;
    }

    m_Lock.unlock();

    return true;
}

void Synth::onSeek(sf::Time) {}

void Synth::makeSound(float freq, int duration) {
    m_Lock.lock();

    m_ClearData = false;
    m_Loaded = true;

    m_AudioData.clear();

    int sampleCount = duration * 44;
    int amplitude = m_Amplitude;
    for (int i = 0; i < sampleCount; i++) {
        if (i < sampleCount / 5) 
            amplitude = floor(m_Amplitude * (i / (double)sampleCount) * 5);
        else if (i > sampleCount / 2) 
            amplitude = floor(m_Amplitude * ((sampleCount - i) / (double)sampleCount));
        else
            amplitude = m_Amplitude;

        m_AudioData.push_back(amplitude * sin(TAU * (freq / 44100) * i));
    }

    m_Lock.unlock();

    if (!m_Started) {
        play();
        m_Started = true;
    }
}

bool Synth::busy() {
    bool isBusy = false;

    if (m_Lock.try_lock()) {
        isBusy = m_Loaded || m_ClearData;

        m_Lock.unlock();
    }

    return isBusy;
}

对于上下文,这些合成器存储在父类拥有的向量中。它们用于表示播放音频的可用通道。父类中总共存储了50个,但是数量可以变化。我怀疑这是否与我的问题有关,但是我想尽我所能通知所有人。

非常感谢您向我的代码提出任何其他批评。

0 个答案:

没有答案