Esempio n. 1
0
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SamplesBuffer *MetronomeTrackNode::readWavFile(const QString &fileName, quint32 &sampleRate)
{
    // Open wave file
    QFile wavFile(fileName);
    if (!wavFile.open(QFile::ReadOnly)) {
        qWarning() << "Failed to open WAV file...";
        return nullptr; // Done
    }

    // Read in the whole thing
    QByteArray wavFileContent = wavFile.readAll();

    // Define the header components
    quint8 fileType[4];
    quint32 fileSize;
    quint8 waveName[4];
    quint8 fmtName[3];
    quint32 fmtLength;
    quint16 fmtType;
    quint16 numberOfChannels;
    quint32 sampleRateXBitsPerSampleXChanngelsDivEight;
    quint16 bitsPerSampleXChannelsDivEightPointOne;
    quint16 bitsPerSample;
    quint8 dataHeader[4];
    quint32 dataSize;

    // Create a data stream to analyze the data
    QDataStream stream(&wavFileContent, QIODevice::ReadOnly);
    stream.setByteOrder(QDataStream::LittleEndian);

    // Now pop off the appropriate data into each header field defined above
    stream.readRawData((char *)fileType, 4); // "RIFF"
    stream >> fileSize; // File Size
    stream.readRawData((char *)waveName, 4); // "WAVE"
    stream.readRawData((char *)fmtName, 4); // "fmt"
    stream >> fmtLength; // Format length
    stream >> fmtType; // Format type
    stream >> numberOfChannels; // Number of channels
    stream >> sampleRate; // Sample rate
    stream >> sampleRateXBitsPerSampleXChanngelsDivEight; // (Sample Rate * BitsPerSample * Channels) / 8
    stream >> bitsPerSampleXChannelsDivEightPointOne; // (BitsPerSample * Channels) / 8.1
    stream >> bitsPerSample; // Bits per sample
    stream.readRawData((char *)dataHeader, 4); // "data" header
    stream >> dataSize; // Data Size

    int samples = dataSize / numberOfChannels / (bitsPerSample/ 8);
    SamplesBuffer *buffer = new SamplesBuffer(numberOfChannels, samples);

    // Now pull out the data
    qint16 sample = 0;
    for (int s = 0; s < samples; ++s) {
        for (int c = 0; c < numberOfChannels; ++c) {
            stream >> sample;
            buffer->set(c, s, sample / 32767.0f);
        }
    }
    return buffer;
}
Esempio n. 2
0
void AudioNode::processReplacing(const SamplesBuffer &in, SamplesBuffer &out, int sampleRate, std::vector<midi::MidiMessage> &midiBuffer)
{
    Q_UNUSED(in);

    if (!isActivated())
        return;

    internalInputBuffer.setFrameLenght(out.getFrameLenght());
    internalOutputBuffer.setFrameLenght(out.getFrameLenght());

    {
        QMutexLocker locker(&mutex);
        for (auto node : connections) { // ask connected nodes to generate audio
            node->processReplacing(internalInputBuffer, internalOutputBuffer, sampleRate, midiBuffer);
        }
    }

    internalOutputBuffer.set(internalInputBuffer); // if we have no plugins inserted the input samples are just copied  to output buffer.

    static SamplesBuffer tempInputBuffer(2);

    // process inserted plugins
    for (int i=0; i < MAX_PROCESSORS_PER_TRACK; ++i) {
        auto processor = processors[i];
        if (processor && !processor->isBypassed()) {
            tempInputBuffer.setFrameLenght(internalOutputBuffer.getFrameLenght());
            tempInputBuffer.set(internalOutputBuffer); // the output from previous plugin is used as input to the next plugin in the chain

            processor->process(tempInputBuffer, internalOutputBuffer, midiBuffer);

            // some plugins are blocking the midi messages. If a VSTi can't generate messages the previous messages list will be sended for the next plugin in the chain. The messages list is cleared only when the plugin can generate midi messages.
            if (processor->isVirtualInstrument() && processor->canGenerateMidiMessages())
                midiBuffer.clear(); // only the fresh messages will be passed by the next plugin in the chain


            auto pulledMessages = pullMidiMessagesGeneratedByPlugins();
            midiBuffer.insert(midiBuffer.end(), pulledMessages.begin(), pulledMessages.end());
        }
    }

    preFaderProcess(internalOutputBuffer); //call overrided preFaderProcess in subclasses to allow some preFader process.

    internalOutputBuffer.applyGain(gain, leftGain, rightGain, boost);

    lastPeak.update(internalOutputBuffer.computePeak());

    postFaderProcess(internalOutputBuffer);

    out.add(internalOutputBuffer);
}