Статика и гудение при генерации и воспроизведении синусоидальных волн с SFML - PullRequest
0 голосов
/ 26 сентября 2018

Я пишу программу, которая должна воспроизводить много синтезированных синусоид в быстрой последовательности.Я использую 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, но их количество может варьироваться.Я сомневаюсь, что это имеет какое-либо отношение к моей проблеме, но я хотел сообщить всем в меру своих возможностей.

Огромное спасибо, открыта для любой другой стороны критики моего кода.

...