如何使用C ++生成音频wav文件的波形

时间:2018-06-18 09:26:50

标签: c++ audio

我目前正在使用C ++来实现我的代码。我的想法是想通过一个程序读取一个wav文件,然后在屏幕上输出它的波形。我已经在那里找到了一些参考文献:C++ Reading the Data part of a WAV file。这是我读取音频文件的代码。我不知道如何生成波形。

class NameIdModel
{
    public string Name { get; set; }
    public int Id { get; set; } 
}

1 个答案:

答案 0 :(得分:1)

我会将此作为评论与代码gists而不是答案,因为它没有直接回答您的问题,但我没有足够的声誉。

我做了你想用Qt做的事情,我的大部分代码来自Qt的文档。您需要找到样本的峰值,然后绘制它。让我分享一些代码,可以让您了解如何执行此操作。

void Waveform::appendSamples()
{
    buffer = audioDecoder->read();
    qreal peak = getPeakValue(buffer.format());
    const qint16 *data = buffer.constData<qint16>();
    int count = buffer.sampleCount() / 2;
    for (int i = 0; i < count; i += 1200){ // I want 40 samples per second currently assuming 48kHz
        double val = data[i]/peak;         
        samples.append(val * 300); // *300 for scaling
    }
}

qreal Waveform::getPeakValue(const QAudioFormat &format)
{
    qreal ret(0);
    if (format.isValid()){
        switch (format.sampleType()) {
            case QAudioFormat::Unknown:
            break;
            case QAudioFormat::Float:
                if (format.sampleSize() != 32)
                    ret = 0;
                else
                    ret = 1.00003;
            break;
            case QAudioFormat::SignedInt:
                if (format.sampleSize() == 32)
                    ret = INT_MAX;
                else if (format.sampleSize() == 16)
                    ret = SHRT_MAX;
                else if (format.sampleSize() == 8)
                    ret = CHAR_MAX;
                break;
            case QAudioFormat::UnSignedInt:
                if (format.sampleSize() == 32)
                    ret = UINT_MAX;
                else if (format.sampleSize() == 16)
                    ret = USHRT_MAX;
                else if (format.sampleSize() == 8)
                    ret = UCHAR_MAX;
            break;
        default:
            break;
        }
    }
    return ret;
}

对于Qt中的绘图部分(可能对您没用)

QSGNode* WaveformRenderer::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
    QSGSimpleRectNode *n = static_cast<QSGSimpleRectNode *>(oldNode);

    if(!n){
        n = new QSGSimpleRectNode();
        n->setColor(Qt::red);
    }

    QVector<double> samples = wav->getSamples(); //retrieve the samples

    int numberOfSamples = samples.size();

    setItemWidth(qreal(numberOfSamples * 2)); //signal stuff for qml

    for(int i = 0; i < numberOfSamples; ++i){
        QSGSimpleRectNode *temp = new QSGSimpleRectNode();
        temp->setColor(Qt::green);
        temp->setRect(i * 2, height()/2 - samples[i], 2, samples[i] * 2);
        n->appendChildNode(temp);
    }
    return n;
}