美文网首页
Qt调用aplay播放PCM

Qt调用aplay播放PCM

作者: 一个三要不起 | 来源:发表于2020-10-21 10:15 被阅读0次

    今天接到个任务,让我用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

    相关文章

      网友评论

          本文标题:Qt调用aplay播放PCM

          本文链接:https://www.haomeiwen.com/subject/yydsmktx.html