summaryrefslogtreecommitdiffstats
path: root/demos/spectrum/app/wavfile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'demos/spectrum/app/wavfile.cpp')
-rw-r--r--demos/spectrum/app/wavfile.cpp205
1 files changed, 50 insertions, 155 deletions
diff --git a/demos/spectrum/app/wavfile.cpp b/demos/spectrum/app/wavfile.cpp
index 74d5918..44c3ac5 100644
--- a/demos/spectrum/app/wavfile.cpp
+++ b/demos/spectrum/app/wavfile.cpp
@@ -78,179 +78,74 @@ struct CombinedHeader
WAVEHeader wave;
};
-
-
-WavFile::WavFile(const QAudioFormat &format, qint64 dataLength)
- : m_format(format)
- , m_dataLength(dataLength)
- , m_dataPosition(0)
-{
-}
-
-bool WavFile::readHeader(QIODevice &device)
-{
- if (!device.isSequential()) {
- if (!device.seek(0))
- return false;
- // XXX: else, assume that current position is the start of the header
- }
-
- CombinedHeader header;
- if (device.read(reinterpret_cast<char *>(&header), sizeof(CombinedHeader)) != sizeof(CombinedHeader))
- return false;
-
- if ((memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0
- || memcmp(&header.riff.descriptor.id, "RIFX", 4) == 0)
- && memcmp(&header.riff.type, "WAVE", 4) == 0
- && memcmp(&header.wave.descriptor.id, "fmt ", 4) == 0
- && (header.wave.audioFormat == 1 || header.wave.audioFormat == 0)) {
-
- // Read off remaining header information
- DATAHeader dataHeader;
-
- if (qFromLittleEndian<quint32>(header.wave.descriptor.size) > sizeof(WAVEHeader)) {
- // Extended data available
- quint16 extraFormatBytes;
- if (device.peek((char*)&extraFormatBytes, sizeof(quint16)) != sizeof(quint16))
- return false;
- const qint64 throwAwayBytes = sizeof(quint16) + qFromLittleEndian<quint16>(extraFormatBytes);
- if (device.read(throwAwayBytes).size() != throwAwayBytes)
- return false;
- }
-
- if (device.read((char*)&dataHeader, sizeof(DATAHeader)) != sizeof(DATAHeader))
- return false;
-
- // Establish format
- if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0)
- m_format.setByteOrder(QAudioFormat::LittleEndian);
- else
- m_format.setByteOrder(QAudioFormat::BigEndian);
-
- int bps = qFromLittleEndian<quint16>(header.wave.bitsPerSample);
- m_format.setChannels(qFromLittleEndian<quint16>(header.wave.numChannels));
- m_format.setCodec("audio/pcm");
- m_format.setFrequency(qFromLittleEndian<quint32>(header.wave.sampleRate));
- m_format.setSampleSize(qFromLittleEndian<quint16>(header.wave.bitsPerSample));
- m_format.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt);
-
- m_dataLength = qFromLittleEndian<quint32>(dataHeader.descriptor.size);
- m_dataPosition = 0;
- }
-
- return true;
-}
-
-bool WavFile::writeHeader(QIODevice &device)
+WavFile::WavFile(QObject *parent)
+ : QFile(parent)
+ , m_headerLength(0)
{
- CombinedHeader header;
- DATAHeader dataHeader;
-
- memset(&header, 0, sizeof(CombinedHeader));
-
- // RIFF header
- if (m_format.byteOrder() == QAudioFormat::LittleEndian)
- strncpy(&header.riff.descriptor.id[0], "RIFF", 4);
- else
- strncpy(&header.riff.descriptor.id[0], "RIFX", 4);
- qToLittleEndian<quint32>(quint32(m_dataLength + sizeof(CombinedHeader) + sizeof(DATAHeader) - sizeof(chunk)),
- reinterpret_cast<unsigned char*>(&header.riff.descriptor.size));
- strncpy(&header.riff.type[0], "WAVE", 4);
-
- // WAVE header
- strncpy(&header.wave.descriptor.id[0], "fmt ", 4);
- qToLittleEndian<quint32>(quint32(16),
- reinterpret_cast<unsigned char*>(&header.wave.descriptor.size));
- qToLittleEndian<quint16>(quint16(1),
- reinterpret_cast<unsigned char*>(&header.wave.audioFormat));
- qToLittleEndian<quint16>(quint16(m_format.channels()),
- reinterpret_cast<unsigned char*>(&header.wave.numChannels));
- qToLittleEndian<quint32>(quint32(m_format.frequency()),
- reinterpret_cast<unsigned char*>(&header.wave.sampleRate));
- qToLittleEndian<quint32>(quint32(m_format.frequency() * m_format.channels() * m_format.sampleSize() / 8),
- reinterpret_cast<unsigned char*>(&header.wave.byteRate));
- qToLittleEndian<quint16>(quint16(m_format.channels() * m_format.sampleSize() / 8),
- reinterpret_cast<unsigned char*>(&header.wave.blockAlign));
- qToLittleEndian<quint16>(quint16(m_format.sampleSize()),
- reinterpret_cast<unsigned char*>(&header.wave.bitsPerSample));
-
- // DATA header
- strncpy(dataHeader.descriptor.id, "data", 4);
- qToLittleEndian<quint32>(quint32(m_dataLength),
- reinterpret_cast<unsigned char*>(&dataHeader.descriptor.size));
- return device.write(reinterpret_cast<const char *>(&header), sizeof(CombinedHeader)) == sizeof(CombinedHeader)
- && device.write(reinterpret_cast<const char*>(&dataHeader), sizeof(DATAHeader)) == sizeof(DATAHeader);
}
-const QAudioFormat& WavFile::format() const
+bool WavFile::open(const QString &fileName)
{
- return m_format;
+ close();
+ setFileName(fileName);
+ return QFile::open(QIODevice::ReadOnly) && readHeader();
}
-qint64 WavFile::dataLength() const
+const QAudioFormat &WavFile::fileFormat() const
{
- return m_dataLength;
+ return m_fileFormat;
}
-qint64 WavFile::headerLength()
+qint64 WavFile::headerLength() const
{
- return sizeof(CombinedHeader);
-}
-
-bool WavFile::writeDataLength(QIODevice &device, qint64 dataLength)
-{
- bool result = false;
- if (!device.isSequential()) {
- device.seek(40);
- unsigned char dataLengthLE[4];
- qToLittleEndian<quint32>(quint32(dataLength), dataLengthLE);
- result = (device.write(reinterpret_cast<const char *>(dataLengthLE), 4) == 4);
- }
- return result;
+return m_headerLength;
}
-qint64 WavFile::readData(QIODevice &device, QByteArray &buffer,
- QAudioFormat outputFormat)
+bool WavFile::readHeader()
{
- // Sanity checks
- if (!outputFormat.isValid())
- outputFormat = m_format;
-
- if (!isPCMS16LE(outputFormat) || !isPCMS16LE(m_format))
- return 0;
-
- if (m_dataPosition == m_dataLength)
- return 0;
-
- // Process
- qint64 result = 0;
-
- const int frameSize = 2 * m_format.channels(); // 16 bit samples
- QVector<char> inputSample(frameSize);
-
- qint16 *output = reinterpret_cast<qint16*>(buffer.data());
+ seek(0);
+ CombinedHeader header;
+ bool result = read(reinterpret_cast<char *>(&header), sizeof(CombinedHeader)) == sizeof(CombinedHeader);
+ if (result) {
+ if ((memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0
+ || memcmp(&header.riff.descriptor.id, "RIFX", 4) == 0)
+ && memcmp(&header.riff.type, "WAVE", 4) == 0
+ && memcmp(&header.wave.descriptor.id, "fmt ", 4) == 0
+ && (header.wave.audioFormat == 1 || header.wave.audioFormat == 0)) {
+
+ // Read off remaining header information
+ DATAHeader dataHeader;
+
+ if (qFromLittleEndian<quint32>(header.wave.descriptor.size) > sizeof(WAVEHeader)) {
+ // Extended data available
+ quint16 extraFormatBytes;
+ if (peek((char*)&extraFormatBytes, sizeof(quint16)) != sizeof(quint16))
+ return false;
+ const qint64 throwAwayBytes = sizeof(quint16) + qFromLittleEndian<quint16>(extraFormatBytes);
+ if (read(throwAwayBytes).size() != throwAwayBytes)
+ return false;
+ }
- while (result < buffer.size()) {
- if (m_dataPosition == m_dataLength)
- break;
+ if (read((char*)&dataHeader, sizeof(DATAHeader)) != sizeof(DATAHeader))
+ return false;
- // XXX only working with particular alignments
- if (device.read(inputSample.data(), inputSample.count())) {
- int inputIdx = 0;
- for (int outputIdx = 0; outputIdx < outputFormat.channels(); ++outputIdx) {
- const qint16* input = reinterpret_cast<const qint16*>(inputSample.data() + 2 * inputIdx);
- *output++ = qFromLittleEndian<qint16>(*input);
- result += 2;
- if (inputIdx < m_format.channels())
- ++inputIdx;
- }
- m_dataPosition += frameSize;
+ // Establish format
+ if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0)
+ m_fileFormat.setByteOrder(QAudioFormat::LittleEndian);
+ else
+ m_fileFormat.setByteOrder(QAudioFormat::BigEndian);
+
+ int bps = qFromLittleEndian<quint16>(header.wave.bitsPerSample);
+ m_fileFormat.setChannels(qFromLittleEndian<quint16>(header.wave.numChannels));
+ m_fileFormat.setCodec("audio/pcm");
+ m_fileFormat.setFrequency(qFromLittleEndian<quint32>(header.wave.sampleRate));
+ m_fileFormat.setSampleSize(qFromLittleEndian<quint16>(header.wave.bitsPerSample));
+ m_fileFormat.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt);
} else {
- break;
+ result = false;
}
}
-
+ m_headerLength = pos();
return result;
}
-