使用QaudioOutput进行实时流式传输
Realtime streaming with QAudioOutput
我正在从事一个C 项目,以读取/流程/播放麦克风阵列系统的原始音频,该音频具有自己的C API。我正在使用QT来编程软件。
从有关QaudioOutput(QT)实时流媒体进行实时流媒体的帖子中,我想跟进并询问有关原始音频数据来自一个大约需要1000ms(1秒)来处理的函数调用该怎么办?我如何仍然能够实现实时音频播放。
大约需要一秒钟的过程,因为我读到写信给Qiodevice :: qaudioformat-> start();建议使用一个时期的字节来防止缓冲底部/超支。http://cell0907.blogspot.sg/2012/10/qt-audio-unput.html
我已经设置了一个qbyTearray和qdataStream,以流从函数调用中收到的数据。
- API是CCMXXX()
- 从麦克风阵列中读取数据返回32位整数的数组
- 32位整数,24位分辨率,8位LSB填充零。
- 它有块大小(设置为1024个样品)x 40麦克风
- 每个块写入大约一个街区,直到书面的字节数接近周期大小/免费字节的数量。
测试:将我的插槽连接到大约50ms的通知,以编写一个价值一个字节的时期。循环缓冲区风格的QByTearray。在读/写入部分中添加了一个Mutex锁定/解锁。
结果:实际播放的实际音频,很短的MS,许多抖动和未录制的声音。
请提供有关如何改进代码的反馈。
设置Qaudioformat
void MainWindow::init_audio_format(){
m_format.setSampleRate(48000); //(8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200, 96000, 192000
m_format.setByteOrder(QAudioFormat::LittleEndian);
m_format.setChannelCount(1);
m_format.setCodec("audio/pcm");
m_format.setSampleSize(32); //(8, 16, 24, 32, 48, 64)
m_format.setSampleType(QAudioFormat::SignedInt); //(SignedInt, UnSignedInt, Float)
m_device = QAudioDeviceInfo::defaultOutputDevice();
QAudioDeviceInfo info(m_device);
if (!info.isFormatSupported(m_format)) {
qWarning() << "Raw audio format not supported by backend, cannot play audio.";
return;
}
}
初始化音频和qbyTearray/datastream
void MainWindow::init_audio_output(){
m_bytearray.resize(65536);
mstream = new QDataStream(&m_bytearray,QIODevice::ReadWrite);
mstream->setByteOrder(QDataStream::LittleEndian);
audio = new QAudioOutput(m_device,m_format,this);
audio->setBufferSize(131072);
audio->setNotifyInterval(50);
m_audiodevice = audio->start();
connect(audio,SIGNAL(notify()),this,SLOT(slot_writedata()));
read_frames();
}
插槽:
void MainWindow::slot_writedata(){
QMutex mutex;
mutex.lock();
read_frames();
mutex.unlock();
}
读取帧:
void MainWindow::read_frames(){
qint32* buffer;
int frameSize, byteCount=0;
DWORD tdFrames, fdFrames;
float fvalue = 0;
qint32 q32value;
frameSize = 40 * mBlockSize; //40 mics
buffer = new int[frameSize];
int periodBytes = audio->periodSize();
int freeBytes = audio->bytesFree();
int chunks = qMin(periodBytes/mBlockSize,freeBytes/mBlockSize);
CcmStartInput();
while(chunks){
CcmReadFrames(buffer,NULL,frameSize,0,&tdFrames,&fdFrames,NULL,CCM_WAIT);
if(tdFrames==0){
break;
}
int diffBytes = periodBytes - byteCount;
if(diffBytes>=(int)sizeof(q32value)*mBlockSize){
for(int x=0;x<mBlockSize;x++){
q32value = (quint32)buffer[x]/256;
*mstream << (qint32)fvalue;
byteCount+=sizeof(q32value);
}
}
else{
for(int x=0;x<(diffBytes/(int)sizeof(q32value));x++){
q32value = (quint32)buffer[x]/256;
*mstream << (qint32) fvalue;
byteCount+=sizeof(q32value);
}
}
--chunks;
}
CcmStopInput();
mPosEnd = mPos + byteCount;
write_frames();
mPos += byteCount;
if(mPos >= m_bytearray.length()){
mPos = 0;
mstream->device()->seek(0); //change mstream pointer back to bytearray start
}
}
写帧:
void MainWindow::write_frames()
{
int len = m_bytearray.length() - mPos;
int bytesWritten = mPosEnd - mPos;
if(len>=audio->periodSize()){
m_audiodevice->write(m_bytearray.data()+mPos, bytesWritten);
}
else{
w_data.replace(0,qAbs(len),m_bytearray.data()+mPos);
w_data.replace(qAbs(len),audio->periodSize()-abs(len),m_bytearray.data());
m_audiodevice->write(w_data.data(),audio->periodSize());
}
}
QT中的音频支持实际上是基本的。目标是以最低的实施和维护成本进行媒体播放。在窗户上,情况尤其糟糕,我认为古老的MME API仍用于播放音频。
因此,QT音频API远非实时时间,使其特别适合此类应用程序。我建议使用Portaudio或Rtaudio,如果可以的话,您仍然可以用QT样式IO设备包装。这将使您在非常低的延迟下访问更好的性能平台音频API和更好的播放性能。
- 通过套接字[TCP]传输数据 如何在C / C ++中打包多个整数并使用send() recv()传输数据
- Angelscript从C++传输数组
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- 从数据库实时显示QT c++中的数据
- 从服务器传输到客户端的消息不会出现
- USB传输的LibUSB C++格式不同
- 在 Windows 8/10 技术中完全实时的屏幕捕获,没有延迟
- 有没有办法使用 c++ 实时阅读文本?
- 在本地网络中通过OpenCV(C++)实时流式传输图像
- 将相机数据从服务器实时流式传输到客户端
- 使用MediaCapture进行实时流式传输
- 用于实时流式传输的 WebM 数据包标头
- 使用QaudioOutput进行实时流式传输
- 实时在语言之间流水线传输或以其他方式传输数据
- 如何在TCP端口上实时传输数据期间减少CPU使用率
- C++ ffmpeg 实时视频传输
- 将实时摄像机源从 RPI 计算模块流式传输到 RPI 3
- 使用 Live555 从连接到 H264 编码器的 IP 摄像机流式传输实时视频
- gstreamer 管道代码,用于通过来自相机的实时流式传输而不是图像显示文本
- Live555可在一个RTSP流中流式传输实时视频和音频