我正在编写一个程序,该程序需要快速连续播放许多合成的正弦波。我正在使用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个,但是数量可以变化。我怀疑这是否与我的问题有关,但是我想尽我所能通知所有人。
非常感谢您向我的代码提出任何其他批评。