下面是寫在QT5讀取音頻輸入,麥克風,和成64K循環緩衝器的地方它的代碼。一旦緩衝區有數據,它將它寫入音頻輸出端,即PC上的揚聲器。這是裸露的骨骼代碼,應該是熟悉聲音設備的好起點。請注意,這裏的聲音輸入和輸出在一個對象中,這可能會導致緩衝區問題。爲了達到這個目的,爲輸入和輸出創建一個單獨的對象。 該程序是在兩個文件中,第一個是qt配置文件(.pro),第二個是main.cpp文件。
#AudioEcho.pro file for QT5.2.1
QT += core
QT -= gui
QT += multimedia widgets
TARGET = AudioEcho
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
//main.cpp file
#include <QDebug>
#include <QIODevice>
#include <QAudioInput>
#include <QAudioOutput>
#include <QCoreApplication>
class myAudio :public QIODevice
{
// Q_OBJECT
public:
QAudioOutput *audioOut;
QAudioInput *audioIn;
myAudio();
~myAudio(){}
void fillBuffer();
QAudioFormat formatIn,formatOut;
QByteArray buff;
char *pbuff;
quint64 RXbuff;
quint64 buffPtr;
protected:
qint64 readData(char *data, qint64 maxlen);
qint64 writeData(const char *data, qint64 len);
qint64 bytesAvailable() const;
};
#define SAMPLE_RATE 22050
#define CHANNELS 1
#define SAMPLE_SIZE 16
#define SAMPLE_TYPE SignedInt
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
myAudio *m= new myAudio();
return a.exec();
}
myAudio::myAudio()
{
formatIn.setSampleRate(SAMPLE_RATE);
formatIn.setChannelCount(CHANNELS);
formatIn.setSampleSize(SAMPLE_SIZE);
formatIn.setCodec("audio/pcm");
formatIn.setByteOrder(QAudioFormat::LittleEndian);
formatIn.setSampleType(QAudioFormat::SAMPLE_TYPE);
formatOut.setSampleRate(SAMPLE_RATE);
formatOut.setChannelCount(CHANNELS);
formatOut.setSampleSize(SAMPLE_SIZE);
formatOut.setCodec("audio/pcm");
formatOut.setByteOrder(QAudioFormat::LittleEndian);
formatOut.setSampleType(QAudioFormat::SAMPLE_TYPE);
//print out the output device setup parameters
QAudioDeviceInfo deviceOut(QAudioDeviceInfo::availableDevices(QAudio::AudioOutput).at(0)); //select output device 0
qDebug()<<"Selected Output device ="<<deviceOut.deviceName();
//print out the input device setup parameters
QAudioDeviceInfo deviceIn(QAudioDeviceInfo::availableDevices(QAudio::AudioInput).at(0)); //select output device 0
qDebug()<<"Selected input device ="<<deviceIn.deviceName();
//configure device
audioOut = new QAudioOutput(deviceOut,formatOut,0);
audioIn = new QAudioInput (deviceIn, formatIn,0);
//print out the device specifications
foreach(const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::availableDevices(QAudio::AudioInput))
{
qDebug() << "\nSuported Input devices";
qDebug() << "\nDevice name: " << deviceInfo.deviceName();
qDebug() << "Supported channel count: " << deviceInfo.supportedChannelCounts();
qDebug() << "Supported Codec: " << deviceInfo.supportedCodecs();
qDebug() << "Supported byte order: " << deviceInfo.supportedByteOrders();
qDebug() << "Supported Sample Rate: " << deviceInfo.supportedSampleRates();
qDebug() << "Supported Sample Size: " << deviceInfo.supportedSampleSizes();
qDebug() << "Supported Sample Type: " << deviceInfo.supportedSampleTypes();
qDebug() << "Preferred Device settings:" << deviceInfo.preferredFormat();
}
foreach(const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::availableDevices(QAudio::AudioOutput))
{
qDebug() << "\nSuported output devices";
qDebug() << "Device name: " << deviceInfo.deviceName();
qDebug() << "Supported channel count: " << deviceInfo.supportedChannelCounts();
qDebug() << "Supported Codec: " << deviceInfo.supportedCodecs();
qDebug() << "Supported byte order: " << deviceInfo.supportedByteOrders();
qDebug() << "Supported Sample Rate: " << deviceInfo.supportedSampleRates();
qDebug() << "Supported Sample Size: " << deviceInfo.supportedSampleSizes();
qDebug() << "Supported Sample Type: " << deviceInfo.supportedSampleTypes();
qDebug() << "Preferred Device settings:" << deviceInfo.preferredFormat();
}
buff.resize(0x10000); //create a rx buffer
pbuff=buff.data(); //get the buff address;
RXbuff=0; //set RX buffer pointer
qDebug()<<"File open"<<open(QIODevice::ReadWrite);
qDebug()<<"is device Sequential="<<isSequential();
audioIn->start(this); //start reading device
audioOut->setVolume(0.5); //volume 0 to 1.0
audioOut->start(this); //start writing to device
}
//QIODevice Class (Protected Functions)This function is called by QIODevice.
//send to output(Speaker)
qint64 myAudio::readData(char *data, qint64 len)
{
static quint64 TXbuff=0;
qint64 total = 0;
while (len > total && RXbuff>TXbuff)//write and synchonise buffers
{
//write data to speaker
memcpy(&data[total],&pbuff[TXbuff%0x10000],2); //copy 2 Bytes
TXbuff+=2; //point to next buffer 16 bit location
total+=2;
}
return total; //the reset interval
}
//audio input (from Microphone)
qint64 myAudio::writeData(const char *data, qint64 len)
{
int total=0;
while (len > total)
{
memcpy(&pbuff[RXbuff%0x10000],&data[total], 2); //write 2Bytes into circular buffer(64K)
RXbuff+=2; //next 16bit buffer location
total+=2; //next data location
}
return (total); //return total number of bytes received
}
qint64 myAudio::bytesAvailable() const{return 0;}
@BrianRoach:我還沒有嘗試過任何東西,因爲我找不到一種方法開始。我知道我可以使用聲音輸入usinq QAudioInput並播放聲音,我可以使用QAudioOutput,但這兩種聲音都可以在文件上運行,即QAudioInput將輸入存儲在文件中,然後QAudioOutput播放該文件中的聲音。這種方法肯定不能在全雙工場景中運行,是嗎?我發現了一些以前的答案,但他們都很老,他們建議使用其他庫,如openAL,portAudio等。我想知道是否有任何使用Qt庫的解決方案。 –