Я пишу программу, которая должна воспроизводить много синтезированных синусоид в быстрой последовательности. Я использую C ++ и SFML для написания этой программы. Я создал класс для представления синтезатора. Он отвечает за генерацию синусоидальной волны и воспроизведение ее по одному аудиопотоку. Однако всякий раз, когда я использую приложение, я получаю много трескучих и трескучих звуков, которые смешиваются. Я не уверен, является ли это проблемой библиотеки, или я генерирую и подаваю в синусоиде неправильно. Вот мой код:
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, но их количество может варьироваться. Я сомневаюсь, что это имеет какое-либо отношение к моей проблеме, но я хотел сообщить всем в меру своих возможностей.
Большое спасибо, открыта для любой другой стороны критики моего кода.
Задача ещё не решена.
Других решений пока нет …