Qt - 重新实现QIODevice,实时听到我自己的声音
Qt - Reimplementation of QIODevice to hear my own voice in realtime
我正在对QIODevice
类进行子类化,以通过QAudioInput
和QAudioOutput
实例写入和读取语音。但是当我在耳机里读到它时,声音每隔几毫秒就会有一点点的削减。它发出的声音非常糟糕,如果我保持麦克风打开,当我关闭它时,声音会持续很长时间。
换句话说:
- 我在麦克风里说"AAAAAA">
- 我在耳机中听到"AA - AA - AA">
我已经尝试使用其他QIODevice
实现,例如QFile
并且效果很好,声音很好。这意味着问题不在我的QAudioInput
和QAudioOutput
实例中。
当我想听到我的声音时,我唯一要做的就是:
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++中为我自己的基于指针的数组分配内存的正确方法
- 将矩阵乘以我自己的输入的向量
- 如何正确包含我自己的标头?
- 如何使用我构建的库,而不会从源代码出错,但不为我自己的项目编译?
- 预期'while'或预期'}' 之前回答是,但我自己无法修复
- 为什么__builtin_popcount比我自己的比特计数功能慢?
- 在wxWidgets的事件中包含我自己的数据的最佳方法是什么?
- 如何在我自己的staticLib中使用staticLib
- 在我自己的堆栈中实现top的问题
- 尝试检查输入的文本与我自己的自定义答案
- 如何在我自己的类中重载"+"和"<<"运算符
- C++:我自己类的动态数组
- 如何在 C++ 中使用我自己的类中的库?
- 如何链接我自己的 .so 文件而不是操作系统捆绑包 .so 文件?
- 如何构建默认使用我自己的构建libc ++的clang?
- 访问另一个类(系统)的非静态字段,就好像它是我自己的字段一样 - 优雅地
- 分发我自己的程序的几个问题
- 尝试编写我自己的字符串类在 gcc 中出现异常
- Qt - 重新实现QIODevice,实时听到我自己的声音
- 编写我自己的push_back功能