今天接到个任务,让我用Qt播放PCM,这个简单,随便一百度就有了。
#ifndef PLAYPCM_H
#define PLAYPCM_H
#include <QObject>
#include <QAudioOutput>
#include <QIODevice>
class PlayPCM : public QObject
{
Q_OBJECT
QAudioOutput *audioOutput = nullptr;
QIODevice *streamOut = nullptr;
#endif
public:
explicit PlayPCM(int sampleRate = 44100, int channels = 2, int sampleSize = 16, QObject *parent = nullptr);
~PlayPCM();
signals:
public slots:
void writePCM(QByteArray array);
};
#endif // PLAYPCM_H
#include "playpcm.h"
#include <QDebug>
#include <QAudioFormat>
#include <QAudioDeviceInfo>
PlayPCM::PlayPCM(int sampleRate, int channels, int sampleSize, QObject *parent) : QObject(parent)
{
//设置采样格式
QAudioFormat audioFormat;
//设置采样率
audioFormat.setSampleRate(sampleRate);
//设置通道数
audioFormat.setChannelCount(channels);
//设置采样大小,一般为8位或16位
audioFormat.setSampleSize(sampleSize);
//设置编码方式
audioFormat.setCodec("audio/pcm");
//设置字节序
audioFormat.setByteOrder(QAudioFormat::LittleEndian);
//设置样本数据类型
audioFormat.setSampleType(QAudioFormat::UnSignedInt);
//音频设备信息
QList<QAudioDeviceInfo> list = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
foreach (QAudioDeviceInfo info, list) {
if (info.isFormatSupported(audioFormat)) {
audioOutput = new QAudioOutput(audioFormat, this);
streamOut = audioOutput->start();
break;
}
}
}
PlayPCM::~PlayPCM()
{
delete audioOutput;
audioOutput = nullptr;
streamOut = nullptr;
}
void PlayPCM::writePCM(QByteArray array)
{
if (streamOut)
streamOut->write(array);
}
#endif
不过在运行的时候出了问题
ALSA lib pcm_hw.c:1788:(_snd_pcm_hw_open) Unknown field slave
嘶~ 好像是alsa源码出了问题,但是又不想去看源码......
我记得arm板上有了aplay这个程序,试试它能不能播WAV,可以的话就参考它的源码自己写一个PCM播放
# aplay -D hw:0,0 a.wav
Playing WAVE 'a.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
可以! 再把WAV掐掉头变成PCM
# aplay -D hw:0,0 a.pcm
Playing raw data 'a.pcm' : Unsigned 8 bit, Rate 8000 Hz, Mono
aplay: set_params:1297: Sample format non available
Available formats:
- S16_LE
- S24_LE
......看来需要指定参数
aplay -D hw:0,0 -r 44100 -c 2 -f s16 a.pcm
Playing raw data 'a.pcm' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
可以播了,去参考参考(复制)aplay的源码,然后发现了aplay输入源可以是 stdin,这就舒服了啊,这下连代码都不用参考了
#ifndef PLAYPCM_H
#define PLAYPCM_H
#include <QObject>
#include <QProcess>
class PlayPCM : public QObject
{
Q_OBJECT
QProcess process;
public:
explicit PlayPCM(int sampleRate = 44100, int channels = 2, int sampleSize = 16, QObject *parent = nullptr);
~PlayPCM();
signals:
public slots:
void writePCM(QByteArray array);
};
#endif // PLAYPCM_H
#include "playpcm.h"
#include <QDebug>
PlayPCM::PlayPCM(int sampleRate, int channels, int sampleSize, QObject *parent) : QObject(parent)
{
char cmd[128];
sprintf(cmd, "aplay -D hw:0,0 -r %d -c %d -f s%d", sampleRate, channels, sampleSize);
process.start(cmd);
if (process.waitForStarted()){
//qDebug() << "PCM player is ready.";
}
}
PlayPCM::~PlayPCM()
{
process.kill();
}
void PlayPCM::writePCM(QByteArray array)
{
if (process.isOpen())
process.write(array);
}
参考:
一定要仔细看的help
aplay -h
网友评论