[英]Where to add the Wav header to data in a live audio server using c++ and qt?
我知道这是一个很长的问题,但是我真的希望您有耐心地阅读它,对我有帮助,因为我似乎在这里已死胡同。
我对c ++客户端服务器和Qt多媒体开发方面非常陌生。 我正在尝试创建一个服务器,该服务器允许使用Qt将音频流传输到客户端。
通过使用Qt的QAudioInput, QAudioDeviceInfo, QAudioFormat
类,我学会了如何录制音频,这与QAudioRecorder
示例中给出的非常不同。 我还学习了如何将wav标头添加到原始音频数据中并使音频可播放。 我用来向音频添加wav标头的函数如下:
void Server::rawToWavQT(QByteArray* arr, long samplingRate, long bytes)
{
long chunksize=0x10;
struct
{
unsigned short wFormatTag;
unsigned short wChannels;
unsigned long dwSamplesPerSec;
unsigned long dwAvgBytesPerSec;
unsigned short wBlockAlign;
unsigned short wBitsPerSample;
} fmt;
long samplecount = bytes/2;
long riffsize = samplecount*2+0x24;
long datasize = samplecount*2;
arr->append("RIFF");// fwrite( "RIFF", 1, 4, wav );
arr->append(QByteArray((const char*)&riffsize, 4));// fwrite( &riffsize, 4, 1, wav );
arr->append("WAVEfmt ");// fwrite( "WAVEfmt ", 1, 8, wav );
arr->append(QByteArray((const char*)&chunksize, 4));// fwrite( &chunksize, 4, 1, wav );
int bitsPerSample = 16;
int bytesPerSample = bitsPerSample/8;
int channel = 2;
fmt.wFormatTag = 1; // PCM
fmt.wChannels = channel; // MONO
fmt.dwSamplesPerSec = samplingRate;
fmt.dwAvgBytesPerSec = samplingRate*channel*bytesPerSample; // 16 bit
fmt.wBlockAlign = channel*bytesPerSample;
fmt.wBitsPerSample = bitsPerSample;
arr->append(QByteArray((const char*)&fmt, sizeof(fmt)));// fwrite( &fmt, sizeof(fmt), 1, wav );
arr->append("data");// fwrite( "data", 1, 4, wav );
arr->append(QByteArray((const char*)&datasize, 4));// fwrite( &datasize, 4, 1, wav );
}
我还得到了一个有关如何使用Qt进行简单的服务器-客户端通信的示例 。 通过该项目,我了解了如何使用Qt服务器和套接字模块开发客户端与服务器之间的通信。
服务器的主窗口类如下所示:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
setFixedSize(size());
}
void MainWindow::on_pushButton_clicked()
{
QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
QAudioDeviceInfo devinfo = devices.at(0);
input = new AudioInput(devinfo, this);
quint16 port = ui->lineEdit->text().toInt();
server = new Server(port, this);
connect(input, SIGNAL(dataReady(QByteArray)), server, SLOT(writeData(QByteArray)));
ui->comboBox->setEnabled(false);
ui->lineEdit->setEnabled(false);
ui->pushButton->setEnabled(false);
}
音频数据提供程序类如下:
AudioInput::AudioInput(QAudioDeviceInfo devinfo, QObject *parent) : QObject(parent)
{
QAudioFormat format;
format.setChannelCount(1);
format.setSampleRate(8000);
format.setSampleSize(8);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::UnSignedInt);
audio = new QAudioInput(devinfo, format, this);
audio->setBufferSize(8192);
device = audio->start();
connect(device, SIGNAL(readyRead()), SLOT(readyRead()));
}
void AudioInput::readyRead()
{
QByteArray data;
//Check the number of samples in input buffer
qint64 len = audio->bytesReady();
//Read sound samples from input device to buffer
if (len > 0)
{
data.resize(len);
device->read(data.data(), len);
}
emit dataReady(data);
}
服务器类如下:
Server::Server(quint16 port, QObject *parent) : QObject(parent)
{
socket = 0;
server = new QTcpServer(this);
connect(server, SIGNAL(newConnection()), SLOT(newConnection()));
server->listen(QHostAddress::Any, port);
}
void Server::newConnection()
{
socket = server->nextPendingConnection();
connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
connect(socket, SIGNAL(destroyed()), SLOT(zeropointer()));
}
void Server::zeropointer()
{
socket = 0;
}
void Server::writeData(QByteArray data)
{
if (socket)
socket->write(data);
}
我现在面临的问题是在写入数据以在服务器中服务时找到合适的阶段来添加wav
标头。 我已经尝试通过使用rawToWavQT
函数将标头添加到writeData
函数中,如上所示,但是在客户端,它工作不正常,我在那里听不到任何正确的声音。 我什至尝试将在客户端接收到的音频数据另存为wav文件,但是将其保存后,我无法生成任何可播放的音频文件,并且与通常的.wav文件相比,文件本身很小。
谢谢你的耐心。
我是您在问题中使用的项目的所有者,我对此进行了一些更改。 修改内容包括错误修复,连接到服务器的多个客户端,客户端协商音频设置和音频记录。
在这里看到它 。
服务器是一个非常基本的实现,我从互联网上的一些阅读中学到了一些东西,从这些阅读中了解了一些东西,以及在Qt附带的多媒体示例中看到的其他一些东西。 不仅仅是一个来源!
希望有帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.