diff options
Diffstat (limited to 'demos/spectrum/app')
-rw-r--r-- | demos/spectrum/app/engine.h | 2 | ||||
-rw-r--r-- | demos/spectrum/app/levelmeter.h | 2 | ||||
-rw-r--r-- | demos/spectrum/app/main.cpp | 2 | ||||
-rw-r--r-- | demos/spectrum/app/spectrograph.h | 2 | ||||
-rw-r--r-- | demos/spectrum/app/spectrumanalyser.cpp | 2 | ||||
-rw-r--r-- | demos/spectrum/app/wavfile.cpp | 168 | ||||
-rw-r--r-- | demos/spectrum/app/wavfile.h | 1 |
7 files changed, 95 insertions, 84 deletions
diff --git a/demos/spectrum/app/engine.h b/demos/spectrum/app/engine.h index b6fe3ed..e14ac83 100644 --- a/demos/spectrum/app/engine.h +++ b/demos/spectrum/app/engine.h @@ -227,7 +227,7 @@ signals: * Level changed * \param rmsLevel RMS level in range 0.0 - 1.0 * \param peakLevel Peak level in range 0.0 - 1.0 - * \param numSamples Number of audio samples analysed + * \param numSamples Number of audio samples analyzed */ void levelChanged(qreal rmsLevel, qreal peakLevel, int numSamples); diff --git a/demos/spectrum/app/levelmeter.h b/demos/spectrum/app/levelmeter.h index 38d13b1..683dba7 100644 --- a/demos/spectrum/app/levelmeter.h +++ b/demos/spectrum/app/levelmeter.h @@ -46,7 +46,7 @@ /** * Widget which displays a vertical audio level meter, indicating the - * RMS and peak levels of the window of audio samples most recently analysed + * RMS and peak levels of the window of audio samples most recently analyzed * by the Engine. */ class LevelMeter : public QWidget { diff --git a/demos/spectrum/app/main.cpp b/demos/spectrum/app/main.cpp index 3bdfb7d..fb5183e 100644 --- a/demos/spectrum/app/main.cpp +++ b/demos/spectrum/app/main.cpp @@ -44,7 +44,7 @@ int main(int argc, char **argv) { QApplication app(argc, argv); - app.setApplicationName("QtMultimedia spectrum analyser"); + app.setApplicationName("QtMultimedia spectrum analyzer"); MainWidget w; #ifdef Q_OS_SYMBIAN diff --git a/demos/spectrum/app/spectrograph.h b/demos/spectrum/app/spectrograph.h index ce59d90..fa4a6cf 100644 --- a/demos/spectrum/app/spectrograph.h +++ b/demos/spectrum/app/spectrograph.h @@ -48,7 +48,7 @@ QT_FORWARD_DECLARE_CLASS(QMouseEvent) /** * Widget which displays a spectrograph showing the frequency spectrum - * of the window of audio samples most recently analysed by the Engine. + * of the window of audio samples most recently analyzed by the Engine. */ class Spectrograph : public QWidget { Q_OBJECT diff --git a/demos/spectrum/app/spectrumanalyser.cpp b/demos/spectrum/app/spectrumanalyser.cpp index c467f61..1cc47a6 100644 --- a/demos/spectrum/app/spectrumanalyser.cpp +++ b/demos/spectrum/app/spectrumanalyser.cpp @@ -124,7 +124,7 @@ void SpectrumAnalyserThread::calculateSpectrum(const QByteArray &buffer, // Calculate the FFT m_fft->calculateFFT(m_output.data(), m_input.data()); - // Analyse output to obtain amplitude and phase for each frequency + // Analyze output to obtain amplitude and phase for each frequency for (int i=2; i<=m_numSamples/2; ++i) { // Calculate frequency of this complex sample m_spectrum[i].frequency = qreal(i * inputFrequency) / (m_numSamples); diff --git a/demos/spectrum/app/wavfile.cpp b/demos/spectrum/app/wavfile.cpp index b9467e3..74d5918 100644 --- a/demos/spectrum/app/wavfile.cpp +++ b/demos/spectrum/app/wavfile.cpp @@ -76,80 +76,84 @@ struct CombinedHeader { RIFFHeader riff; WAVEHeader wave; - DATAHeader data; }; -static const int HeaderLength = sizeof(CombinedHeader); WavFile::WavFile(const QAudioFormat &format, qint64 dataLength) - : m_format(format) - , m_dataLength(dataLength) + : m_format(format) + , m_dataLength(dataLength) + , m_dataPosition(0) { - } bool WavFile::readHeader(QIODevice &device) { - bool result = true; - - if (!device.isSequential()) - result = device.seek(0); - // else, assume that current position is the start of the header - - if (result) { - CombinedHeader header; - result = (device.read(reinterpret_cast<char *>(&header), HeaderLength) == HeaderLength); - 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 // PCM - ) { - if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0) - m_format.setByteOrder(QAudioFormat::LittleEndian); - else - m_format.setByteOrder(QAudioFormat::BigEndian); - - 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)); - - switch(header.wave.bitsPerSample) { - case 8: - m_format.setSampleType(QAudioFormat::UnSignedInt); - break; - case 16: - m_format.setSampleType(QAudioFormat::SignedInt); - break; - default: - result = false; - } - - m_dataLength = device.size() - HeaderLength; - } else { - result = false; - } + 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 result; + return true; } bool WavFile::writeHeader(QIODevice &device) { CombinedHeader header; + DATAHeader dataHeader; - memset(&header, 0, HeaderLength); + 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 + HeaderLength - 8), + 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); @@ -171,11 +175,12 @@ bool WavFile::writeHeader(QIODevice &device) reinterpret_cast<unsigned char*>(&header.wave.bitsPerSample)); // DATA header - strncpy(&header.data.descriptor.id[0], "data", 4); + strncpy(dataHeader.descriptor.id, "data", 4); qToLittleEndian<quint32>(quint32(m_dataLength), - reinterpret_cast<unsigned char*>(&header.data.descriptor.size)); + reinterpret_cast<unsigned char*>(&dataHeader.descriptor.size)); - return (device.write(reinterpret_cast<const char *>(&header), HeaderLength) == HeaderLength); + 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 @@ -190,7 +195,7 @@ qint64 WavFile::dataLength() const qint64 WavFile::headerLength() { - return HeaderLength; + return sizeof(CombinedHeader); } bool WavFile::writeDataLength(QIODevice &device, qint64 dataLength) @@ -205,42 +210,47 @@ bool WavFile::writeDataLength(QIODevice &device, qint64 dataLength) return result; } -#include <QFile> -#include <QTextStream> - qint64 WavFile::readData(QIODevice &device, QByteArray &buffer, QAudioFormat outputFormat) { - if (QAudioFormat() == outputFormat) + // 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; - QFile file("wav.txt"); - file.open(QIODevice::WriteOnly | QIODevice::Text); - QTextStream stream; - stream.setDevice(&file); - - if (isPCMS16LE(outputFormat) && isPCMS16LE(m_format)) { - QVector<char> inputSample(2 * m_format.channels()); - - qint16 *output = reinterpret_cast<qint16*>(buffer.data()); - - while (result < buffer.size()) { - 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; - } - } else { - break; + const int frameSize = 2 * m_format.channels(); // 16 bit samples + QVector<char> inputSample(frameSize); + + qint16 *output = reinterpret_cast<qint16*>(buffer.data()); + + while (result < buffer.size()) { + if (m_dataPosition == m_dataLength) + break; + + // 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; + } else { + break; } } + return result; } diff --git a/demos/spectrum/app/wavfile.h b/demos/spectrum/app/wavfile.h index f2f3304..fc14b08 100644 --- a/demos/spectrum/app/wavfile.h +++ b/demos/spectrum/app/wavfile.h @@ -77,6 +77,7 @@ public: private: QAudioFormat m_format; qint64 m_dataLength; + qint64 m_dataPosition; }; #endif |