From c9b3f247c7b1b2daa5c47dcc2184be186c9613a4 Mon Sep 17 00:00:00 2001 From: Lev Zelenskiy Date: Fri, 24 Feb 2012 13:00:35 +1000 Subject: Audio decoder example. Change-Id: I0f9fb755ef8bc6f66696a06996ac7a9f13de69cc Reviewed-by: Michael Goddard --- examples/audiodecoder/audiodecoder.cpp | 188 ++++++++++++++++++++++++++++++ examples/audiodecoder/audiodecoder.h | 92 +++++++++++++++ examples/audiodecoder/audiodecoder.pro | 13 +++ examples/audiodecoder/main.cpp | 93 +++++++++++++++ examples/audiodecoder/wavefilewriter.cpp | 192 +++++++++++++++++++++++++++++++ examples/audiodecoder/wavefilewriter.h | 69 +++++++++++ 6 files changed, 647 insertions(+) create mode 100644 examples/audiodecoder/audiodecoder.cpp create mode 100644 examples/audiodecoder/audiodecoder.h create mode 100644 examples/audiodecoder/audiodecoder.pro create mode 100644 examples/audiodecoder/main.cpp create mode 100644 examples/audiodecoder/wavefilewriter.cpp create mode 100644 examples/audiodecoder/wavefilewriter.h (limited to 'examples') diff --git a/examples/audiodecoder/audiodecoder.cpp b/examples/audiodecoder/audiodecoder.cpp new file mode 100644 index 000000000..7263a1085 --- /dev/null +++ b/examples/audiodecoder/audiodecoder.cpp @@ -0,0 +1,188 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "audiodecoder.h" +#include + +AudioDecoder::AudioDecoder(bool isPlayback, bool isDelete) + : m_cout(stdout, QIODevice::WriteOnly) +{ + m_isPlayback = isPlayback; + m_isDelete = isDelete; + + // Make sure the data we receive is in correct PCM format. + // Our wav file writer only supports SignedInt sample type. + QAudioFormat format; + format.setChannels(2); + format.setSampleSize(16); + format.setFrequency(48000); + format.setCodec("audio/pcm"); + format.setSampleType(QAudioFormat::SignedInt); + m_decoder.setAudioFormat(format); + + connect(&m_decoder, SIGNAL(bufferReady()), this, SLOT(bufferReady())); + connect(&m_decoder, SIGNAL(error(QAudioDecoder::Error)), this, SLOT(error(QAudioDecoder::Error))); + connect(&m_decoder, SIGNAL(stateChanged(QAudioDecoder::State)), this, SLOT(stateChanged(QAudioDecoder::State))); + connect(&m_decoder, SIGNAL(finished()), this, SLOT(finished())); + connect(&m_decoder, SIGNAL(positionChanged(qint64)), this, SLOT(updateProgress())); + connect(&m_decoder, SIGNAL(durationChanged(qint64)), this, SLOT(updateProgress())); + + connect(&m_soundEffect, SIGNAL(statusChanged()), this, SLOT(playbackStatusChanged())); + connect(&m_soundEffect, SIGNAL(playingChanged()), this, SLOT(playingChanged())); + + m_progress = -1.0; +} + +void AudioDecoder::setSourceFilename(const QString &fileName) +{ + m_decoder.setSourceFilename(fileName); +} + +void AudioDecoder::start() +{ + m_decoder.start(); +} + +void AudioDecoder::stop() +{ + m_decoder.stop(); +} + +void AudioDecoder::setTargetFilename(const QString &fileName) +{ + m_targetFilename = fileName; +} + +void AudioDecoder::bufferReady() +{ + // read a buffer from audio decoder + QAudioBuffer buffer = m_decoder.read(); + if (!buffer.isValid()) + return; + + if (!m_fileWriter.isOpen() && !m_fileWriter.open(m_targetFilename, buffer.format())) { + m_decoder.stop(); + return; + } + + m_fileWriter.write(buffer); +} + +void AudioDecoder::error(QAudioDecoder::Error error) +{ + switch (error) { + case QAudioDecoder::NoError: + return; + case QAudioDecoder::ResourceError: + m_cout << "Resource error" << endl; + break; + case QAudioDecoder::FormatError: + m_cout << "Format error" << endl; + break; + case QAudioDecoder::AccessDeniedError: + m_cout << "Access denied error" << endl; + break; + case QAudioDecoder::ServiceMissingError: + m_cout << "Service missing error" << endl; + break; + } + + emit done(); +} + +void AudioDecoder::stateChanged(QAudioDecoder::State newState) +{ + switch (newState) { + case QAudioDecoder::DecodingState: + m_cout << "Decoding..." << endl; + break; + case QAudioDecoder::StoppedState: + m_cout << "Decoding stopped" << endl; + break; + } +} + +void AudioDecoder::finished() +{ + if (!m_fileWriter.close()) + m_cout << "Failed to finilize output file" << endl; + + m_cout << "Decoding finished" << endl; + + if (m_isPlayback) { + m_cout << "Starting playback" << endl; + m_soundEffect.setSource(QUrl::fromLocalFile(m_targetFilename)); + m_soundEffect.play(); + } else { + emit done(); + } +} + +void AudioDecoder::playbackStatusChanged() +{ + if (m_soundEffect.status() == QSoundEffect::Error) { + m_cout << "Playback error" << endl; + emit done(); + } +} + +void AudioDecoder::playingChanged() +{ + if (!m_soundEffect.isPlaying()) { + m_cout << "Playback finished" << endl; + if (m_isDelete) + QFile::remove(m_targetFilename); + emit done(); + } +} + +void AudioDecoder::updateProgress() +{ + qint64 position = m_decoder.position(); + qint64 duration = m_decoder.duration(); + qreal progress = m_progress; + if (position >= 0 && duration > 0) + progress = position / (qreal)duration; + + if (progress > m_progress + 0.1) { + m_cout << "Decoding progress: " << (int)(progress * 100.0) << "%" << endl; + m_progress = progress; + } +} diff --git a/examples/audiodecoder/audiodecoder.h b/examples/audiodecoder/audiodecoder.h new file mode 100644 index 000000000..63dd8233f --- /dev/null +++ b/examples/audiodecoder/audiodecoder.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef AUDIODECODER_H +#define AUDIODECODER_H + +#include +#include "wavefilewriter.h" +#include +#include + +QT_USE_NAMESPACE + +class AudioDecoder : public QObject +{ + Q_OBJECT +public: + AudioDecoder(bool isPlayback, bool isDelete); + ~AudioDecoder() { } + + void setSourceFilename(const QString &fileName); + void start(); + void stop(); + + void setTargetFilename(const QString &fileName); + +Q_SIGNALS: + void done(); + +public slots: + void bufferReady(); + void error(QAudioDecoder::Error error); + void stateChanged(QAudioDecoder::State newState); + void finished(); + + void playbackStatusChanged(); + void playingChanged(); + +private slots: + void updateProgress(); + +private: + bool m_isPlayback; + bool m_isDelete; + QAudioDecoder m_decoder; + QTextStream m_cout; + + QString m_targetFilename; + WaveFileWriter m_fileWriter; + QSoundEffect m_soundEffect; + + qreal m_progress; +}; + +#endif // AUDIODECODER_H diff --git a/examples/audiodecoder/audiodecoder.pro b/examples/audiodecoder/audiodecoder.pro new file mode 100644 index 000000000..20e660bff --- /dev/null +++ b/examples/audiodecoder/audiodecoder.pro @@ -0,0 +1,13 @@ +TEMPLATE = app +TARGET = audiodecoder + +CONFIG += qt warn_on + +HEADERS = \ + audiodecoder.h \ + wavefilewriter.h +SOURCES = main.cpp \ + audiodecoder.cpp \ + wavefilewriter.cpp + +QT+= multimedia multimedia-private console diff --git a/examples/audiodecoder/main.cpp b/examples/audiodecoder/main.cpp new file mode 100644 index 000000000..b4b1700ff --- /dev/null +++ b/examples/audiodecoder/main.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +#include +#include +#include "audiodecoder.h" + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + + QTextStream cout(stdout, QIODevice::WriteOnly); + if (app.arguments().size() < 2) { + cout << "Usage: audiodecoder [-p] [-pd] SOURCEFILE [TARGETFILE]" << endl; + cout << "Set -p option if you want to play output file." << endl; + cout << "Set -pd option if you want to play output file and delete it after successful playback." << endl; + cout << "Default TARGETFILE name is \"out.wav\" in the same directory as the source file." << endl; + return 0; + } + + bool isPlayback = false; + bool isDelete = false; + + if (app.arguments().at(1) == "-p") + isPlayback = true; + else if (app.arguments().at(1) == "-pd") { + isPlayback = true; + isDelete = true; + } + + QFileInfo sourceFile; + QFileInfo targetFile; + + int sourceFileIndex = (isPlayback || isDelete) ? 2 : 1; + if (app.arguments().size() <= sourceFileIndex) { + cout << "Error: source filename is not specified." << endl; + return 0; + } + sourceFile.setFile(app.arguments().at(sourceFileIndex)); + if (app.arguments().size() > sourceFileIndex + 1) + targetFile.setFile(app.arguments().at(sourceFileIndex + 1)); + else + targetFile.setFile(sourceFile.dir().absoluteFilePath("out.wav")); + + AudioDecoder decoder(isPlayback, isDelete); + QObject::connect(&decoder, SIGNAL(done()), &app, SLOT(quit())); + decoder.setSourceFilename(sourceFile.absoluteFilePath()); + decoder.setTargetFilename(targetFile.absoluteFilePath()); + decoder.start(); + + return app.exec(); +}; diff --git a/examples/audiodecoder/wavefilewriter.cpp b/examples/audiodecoder/wavefilewriter.cpp new file mode 100644 index 000000000..218e68daa --- /dev/null +++ b/examples/audiodecoder/wavefilewriter.cpp @@ -0,0 +1,192 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "wavefilewriter.h" + +struct Q_PACKED chunk +{ + char id[4]; + quint32 size; +}; + +struct Q_PACKED RIFFHeader +{ + chunk descriptor; // "RIFF" + char type[4]; // "WAVE" +}; + +struct Q_PACKED WAVEHeader +{ + chunk descriptor; + quint16 audioFormat; + quint16 numChannels; + quint32 sampleRate; + quint32 byteRate; + quint16 blockAlign; + quint16 bitsPerSample; +}; + +struct Q_PACKED DATAHeader +{ + chunk descriptor; +}; + +struct Q_PACKED CombinedHeader +{ + RIFFHeader riff; + WAVEHeader wave; + DATAHeader data; +}; +static const int HeaderLength = sizeof(CombinedHeader); + + +WaveFileWriter::WaveFileWriter(QObject *parent) + : QObject(parent) + , m_dataLength(0) +{ +} + +WaveFileWriter::~WaveFileWriter() +{ + close(); +} + +bool WaveFileWriter::open(const QString& fileName, const QAudioFormat& format) +{ + if (file.isOpen()) + return false; // file already open + + if (format.codec() != "audio/pcm" || format.sampleType() != QAudioFormat::SignedInt) + return false; // data format is not supported + + file.setFileName(fileName); + if (!file.open(QIODevice::WriteOnly)) + return false; // unable to open file for writing + + if (!writeHeader(format)) + return false; + + m_format = format; + return true; +} + +bool WaveFileWriter::write(const QAudioBuffer& buffer) +{ + if (buffer.format() != m_format) + return false; // buffer format has changed + + qint64 written = file.write((const char*)buffer.constData(), buffer.byteCount()); + m_dataLength += written; + return written == buffer.byteCount(); +} + +bool WaveFileWriter::close() +{ + bool result = false; + if (file.isOpen()) { + Q_ASSERT(m_dataLength < INT_MAX); + result = writeDataLength(); + + m_dataLength = 0; + file.close(); + } + return result; +} + +bool WaveFileWriter::writeHeader(const QAudioFormat& format) +{ + // check if format is supported + if (format.byteOrder() == QAudioFormat::BigEndian || format.sampleType() != QAudioFormat::SignedInt) + return false; + + CombinedHeader header; + memset(&header, 0, HeaderLength); + +#ifndef Q_LITTLE_ENDIAN + // only implemented for LITTLE ENDIAN + return false; +#else + // RIFF header + memcpy(header.riff.descriptor.id, "RIFF", 4); + header.riff.descriptor.size = 0; // this will be updated with correct duration: + // m_dataLength + HeaderLength - 8 + // WAVE header + memcpy(header.riff.type, "WAVE", 4); + memcpy(header.wave.descriptor.id, "fmt ", 4); + header.wave.descriptor.size = quint32(16); + header.wave.audioFormat = quint16(1); + header.wave.numChannels = quint16(format.channels()); + header.wave.sampleRate = quint32(format.sampleRate()); + header.wave.byteRate = quint32(format.sampleRate() * format.channels() * format.sampleSize() / 8); + header.wave.blockAlign = quint16(format.channels() * format.sampleSize() / 8); + header.wave.bitsPerSample = quint16(format.sampleSize()); + + // DATA header + memcpy(header.data.descriptor.id,"data", 4); + header.data.descriptor.size = 0; // this will be updated with correct data length: m_dataLength + + return (file.write(reinterpret_cast(&header), HeaderLength) == HeaderLength); +#endif +} + +bool WaveFileWriter::writeDataLength() +{ +#ifndef Q_LITTLE_ENDIAN + // only implemented for LITTLE ENDIAN + return false; +#endif + + if (file.isSequential()) + return false; + + // seek to RIFF header size, see header.riff.descriptor.size above + if (!file.seek(4)) + return false; + + quint32 length = m_dataLength + HeaderLength - 8; + if (file.write(reinterpret_cast(&length), 4) != 4) + return false; + + // seek to DATA header size, see header.data.descriptor.size above + if (!file.seek(40)) + return false; + + return file.write(reinterpret_cast(&m_dataLength), 4) == 4; +} diff --git a/examples/audiodecoder/wavefilewriter.h b/examples/audiodecoder/wavefilewriter.h new file mode 100644 index 000000000..a3c2df4c4 --- /dev/null +++ b/examples/audiodecoder/wavefilewriter.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WAVEFILEWRITER_H +#define WAVEFILEWRITER_H + +#include +#include +#include + +class WaveFileWriter : public QObject +{ + Q_OBJECT +public: + explicit WaveFileWriter(QObject *parent = 0); + ~WaveFileWriter(); + + bool open(const QString& fileName, const QAudioFormat& format); + bool write(const QAudioBuffer& buffer); + bool close(); + bool isOpen() const { return file.isOpen(); } + +private: + bool writeHeader(const QAudioFormat& format); + bool writeDataLength(); + + QFile file; + QAudioFormat m_format; + qint64 m_dataLength; +}; + +#endif // WAVEFILEWRITER_H -- cgit v1.2.3