gpt4 book ai didi

c++ - Qt - 重新实现 QIODevice 以实时听到我自己的声音

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:38:11 27 4
gpt4 key购买 nike

我正在对 QIODevice 类进行子类化,以通过 QAudioInputQAudioOutput 实例编写和读取语音。但是当我用耳机读它时,声音几乎每隔几毫秒就会中断一次。它发出的声音非常糟糕,如果我一直打开麦克风,当我关闭它时,声音会持续很长时间。

换句话说:

  • 我对着麦克风说“AAAAAA”
  • 我在耳机中听到“AA - AA - AA”的声音

我已经尝试使用其他QIODevice 实现,例如QFile,效果很好,声音也不错。这意味着问题不在我的 QAudioInputQAudioOutput 实例中。

当我想听到自己的声音时,我唯一做的就是:

void startrecording()
{
_audioInput->start(_audioBuffer);
_audioOutput->start(_audioBuffer);
// Start the output after didn't really change the sound
// QTimer::singleShot(500, [this] { _audioOutput->start(_audioBuffer); });
}

现在这是我的 AudioBuffer

// .h
class AudioBuffer : public QIODevice
{
Q_OBJECT

public:
AudioBuffer();

protected:
qint64 writeData(const char* data, qint64 len) override;
qint64 readData(char* data, qint64 maxlen) override;

private:
static const int MAXSIZE = 1024 * 1024;

std::array<char, MAXSIZE> _buffer;
qint64 _writePosition;
qint64 _readPosition;
qint64 _currentBufferLength;
};
// .cpp
AudioBuffer::AudioBuffer()
{
_writePosition = 0;
_readPosition = 0;
_currentBufferLength = 0;
}

qint64 AudioBuffer::writeData(const char* data, qint64 len)
{
qDebug() << "--- writing ---" << data;

std::string content = data;

if ((_writePosition + content.size()) > MAXSIZE)
{
qint64 firstData = MAXSIZE - _writePosition;
memcpy(&_buffer[_writePosition], content.data(), firstData);
memcpy(&_buffer[0], content.data() + firstData, content.size() - firstData);
}
else
{
memcpy(&_buffer[_writePosition], content.data(), content.size());
}

_writePosition = (_writePosition + content.size()) % MAXSIZE;
_currentBufferLength += content.size();

return len;
}

qint64 AudioBuffer::readData(char* data, qint64 maxlen)
{
if (_currentBufferLength <= 0) return 0;

qint64 writeLen = std::min(maxlen, _currentBufferLength);
if ((writeLen + _readPosition) > MAXSIZE)
{
qint64 firstData = MAXSIZE - _readPosition;
memcpy(data, &_buffer[_readPosition], firstData);
memcpy(data + firstData, &_buffer[0], writeLen - firstData);
}
else
{
memcpy(data, &_buffer[_readPosition], writeLen);
}

qDebug() << "--- reading ---" << data;

_readPosition = (_readPosition + writeLen) % MAXSIZE;
_currentBufferLength -= writeLen;

return writeLen;
}

qDebug 数据返回相同的输出,只是 readData 调用次数少于 writeData 但缓冲区被正确读取。

输出(不含数据)如下(持续 5 秒)。我不知道这是否意味着什么,但更多的时间过去了,与 readData

相比,更多的 writeData 被调用
--- writing --- x1
--- reading --- x1
--- writing --- x1
--- reading --- x1
--- writing --- x2
--- reading --- x1
--- writing --- x1
--- reading --- x1
--- writing --- x1
--- reading --- x1
--- writing --- x1
--- reading --- x1
--- writing --- x1
--- reading --- x1
--- writing --- x3
--- reading --- x1
--- writing --- x1
--- reading --- x1
--- writing --- x6
--- reading --- x1
--- writing --- x9
--- reading --- x1
--- writing --- x13
--- reading --- x1
--- writing --- x1
--- reading --- x1
--- writing --- x20
--- reading --- x1
--- writing --- x1
--- reading --- x1
--- writing --- x26
--- reading --- x1
--- writing --- x26
--- reading --- x1
--- writing --- x4
input stop
--- reading --- x2

最佳答案

所以经过一些尝试,在这种情况下,似乎使用QBuffer 可以代替我的AudioBuffer

然后,要小心,如果在同一个线程中同时读写,会造成一些卡顿。

但在我的例子中,我需要将数据发送到服务器,然后服务器将音频发送到每个能够听到它的客户端。所以 QBuffer 是不够的。

这是我的新实现

// Moving in different thread
_audioInput->moveToThread(&_inputThread);
_audioOutput->moveToThread(&_outputThread);

_audioInput->start(_audioBuffer);
_audioOutput->start(_audioBuffer);
// .cpp
class AudioBuffer : public QBuffer
{
Q_OBJECT

public:
AudioBuffer(/* Whatever you need for your server connection */);

protected:
/// Override the QBuffer method
qint64 writeData(const char* data, qint64 len) override;

/// Connect this method with the signal emit when your server send new audio
/// This is a string but it can be whatever you want according to your server
void getServerAudio(const std::string& audio);
};
// .h
AudioBuffer::AudioBuffer(/* Whatever you need for your server connection */)
{
// Connect your server with AudioBuffer::getServerAudio
}

qint64 AudioBuffer::writeData(const char* data, qint64 len)
{
// Send that the client send a new audio to the server
std::string audio = data;
// This is an example
sendAudioToServer(audio);

return len;
}

void AudioBuffer::getServerAudio(const std::string& audio)
{
// When you get a new audio from the server, you can hear it (so you write data into the buffer)
QBuffer::writeData(audio.c_str(), audio.size());
}

关于c++ - Qt - 重新实现 QIODevice 以实时听到我自己的声音,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57593939/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com