Changeset 846 for trunk/demos/spectrum/app/wavfile.cpp
- Timestamp:
- May 5, 2011, 5:36:53 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/vendor/nokia/qt/4.7.2 (added) merged: 845 /branches/vendor/nokia/qt/current merged: 844 /branches/vendor/nokia/qt/4.6.3 removed
- Property svn:mergeinfo changed
-
trunk/demos/spectrum/app/wavfile.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 201 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation ([email protected]) … … 77 77 RIFFHeader riff; 78 78 WAVEHeader wave; 79 DATAHeader data;80 79 }; 81 80 82 static const int HeaderLength = sizeof(CombinedHeader); 83 84 85 WavFile::WavFile(const QAudioFormat &format, qint64 dataLength) 86 : m_format(format) 87 , m_dataLength(dataLength) 81 WavFile::WavFile(QObject *parent) 82 : QFile(parent) 83 , m_headerLength(0) 88 84 { 89 85 90 86 } 91 87 92 bool WavFile:: readHeader(QIODevice &device)88 bool WavFile::e) 93 89 { 94 bool result = true; 90 close(); 91 setFileName(fileName); 92 return QFile::open(QIODevice::ReadOnly) && readHeader(); 93 } 95 94 96 if (!device.isSequential()) 97 result = device.seek(0); 98 // else, assume that current position is the start of the header 95 const QAudioFormat &WavFile::fileFormat() const 96 { 97 return m_fileFormat; 98 } 99 99 100 101 102 103 104 105 106 107 108 109 100 110 if (result) { 101 CombinedHeader header; 102 result = (device.read(reinterpret_cast<char *>(&header), HeaderLength) == HeaderLength); 103 if (result) { 104 if ((memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0 105 || memcmp(&header.riff.descriptor.id, "RIFX", 4) == 0) 106 && memcmp(&header.riff.type, "WAVE", 4) == 0 107 && memcmp(&header.wave.descriptor.id, "fmt ", 4) == 0 108 && header.wave.audioFormat == 1 // PCM 109 ) { 110 if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0) 111 m_format.setByteOrder(QAudioFormat::LittleEndian); 112 else 113 m_format.setByteOrder(QAudioFormat::BigEndian); 111 if ((memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0 112 || memcmp(&header.riff.descriptor.id, "RIFX", 4) == 0) 113 && memcmp(&header.riff.type, "WAVE", 4) == 0 114 && memcmp(&header.wave.descriptor.id, "fmt ", 4) == 0 115 && (header.wave.audioFormat == 1 || header.wave.audioFormat == 0)) { 114 116 115 m_format.setChannels(qFromLittleEndian<quint16>(header.wave.numChannels)); 116 m_format.setCodec("audio/pcm"); 117 m_format.setFrequency(qFromLittleEndian<quint32>(header.wave.sampleRate)); 118 m_format.setSampleSize(qFromLittleEndian<quint16>(header.wave.bitsPerSample)); 117 // Read off remaining header information 118 DATAHeader dataHeader; 119 119 120 switch(header.wave.bitsPerSample) { 121 case 8: 122 m_format.setSampleType(QAudioFormat::UnSignedInt); 123 break; 124 case 16: 125 m_format.setSampleType(QAudioFormat::SignedInt); 126 break; 127 default: 128 result = false; 129 } 120 if (qFromLittleEndian<quint32>(header.wave.descriptor.size) > sizeof(WAVEHeader)) { 121 // Extended data available 122 quint16 extraFormatBytes; 123 if (peek((char*)&extraFormatBytes, sizeof(quint16)) != sizeof(quint16)) 124 return false; 125 const qint64 throwAwayBytes = sizeof(quint16) + qFromLittleEndian<quint16>(extraFormatBytes); 126 if (read(throwAwayBytes).size() != throwAwayBytes) 127 return false; 128 } 130 129 131 m_dataLength = device.size() - HeaderLength; 132 } else { 133 result = false; 134 } 130 if (read((char*)&dataHeader, sizeof(DATAHeader)) != sizeof(DATAHeader)) 131 return false; 132 133 // Establish format 134 if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0) 135 m_fileFormat.setByteOrder(QAudioFormat::LittleEndian); 136 else 137 m_fileFormat.setByteOrder(QAudioFormat::BigEndian); 138 139 int bps = qFromLittleEndian<quint16>(header.wave.bitsPerSample); 140 m_fileFormat.setChannels(qFromLittleEndian<quint16>(header.wave.numChannels)); 141 m_fileFormat.setCodec("audio/pcm"); 142 m_fileFormat.setFrequency(qFromLittleEndian<quint32>(header.wave.sampleRate)); 143 m_fileFormat.setSampleSize(qFromLittleEndian<quint16>(header.wave.bitsPerSample)); 144 m_fileFormat.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt); 145 } else { 146 result = false; 135 147 } 136 148 } 137 149 m_headerLength = pos(); 138 150 return result; 139 151 } 140 141 bool WavFile::writeHeader(QIODevice &device)142 {143 CombinedHeader header;144 145 memset(&header, 0, HeaderLength);146 147 // RIFF header148 if (m_format.byteOrder() == QAudioFormat::LittleEndian)149 strncpy(&header.riff.descriptor.id[0], "RIFF", 4);150 else151 strncpy(&header.riff.descriptor.id[0], "RIFX", 4);152 qToLittleEndian<quint32>(quint32(m_dataLength + HeaderLength - 8),153 reinterpret_cast<unsigned char*>(&header.riff.descriptor.size));154 strncpy(&header.riff.type[0], "WAVE", 4);155 156 // WAVE header157 strncpy(&header.wave.descriptor.id[0], "fmt ", 4);158 qToLittleEndian<quint32>(quint32(16),159 reinterpret_cast<unsigned char*>(&header.wave.descriptor.size));160 qToLittleEndian<quint16>(quint16(1),161 reinterpret_cast<unsigned char*>(&header.wave.audioFormat));162 qToLittleEndian<quint16>(quint16(m_format.channels()),163 reinterpret_cast<unsigned char*>(&header.wave.numChannels));164 qToLittleEndian<quint32>(quint32(m_format.frequency()),165 reinterpret_cast<unsigned char*>(&header.wave.sampleRate));166 qToLittleEndian<quint32>(quint32(m_format.frequency() * m_format.channels() * m_format.sampleSize() / 8),167 reinterpret_cast<unsigned char*>(&header.wave.byteRate));168 qToLittleEndian<quint16>(quint16(m_format.channels() * m_format.sampleSize() / 8),169 reinterpret_cast<unsigned char*>(&header.wave.blockAlign));170 qToLittleEndian<quint16>(quint16(m_format.sampleSize()),171 reinterpret_cast<unsigned char*>(&header.wave.bitsPerSample));172 173 // DATA header174 strncpy(&header.data.descriptor.id[0], "data", 4);175 qToLittleEndian<quint32>(quint32(m_dataLength),176 reinterpret_cast<unsigned char*>(&header.data.descriptor.size));177 178 return (device.write(reinterpret_cast<const char *>(&header), HeaderLength) == HeaderLength);179 }180 181 const QAudioFormat& WavFile::format() const182 {183 return m_format;184 }185 186 qint64 WavFile::dataLength() const187 {188 return m_dataLength;189 }190 191 qint64 WavFile::headerLength()192 {193 return HeaderLength;194 }195 196 bool WavFile::writeDataLength(QIODevice &device, qint64 dataLength)197 {198 bool result = false;199 if (!device.isSequential()) {200 device.seek(40);201 unsigned char dataLengthLE[4];202 qToLittleEndian<quint32>(quint32(dataLength), dataLengthLE);203 result = (device.write(reinterpret_cast<const char *>(dataLengthLE), 4) == 4);204 }205 return result;206 }207 208 #include <QFile>209 #include <QTextStream>210 211 qint64 WavFile::readData(QIODevice &device, QByteArray &buffer,212 QAudioFormat outputFormat)213 {214 if (QAudioFormat() == outputFormat)215 outputFormat = m_format;216 217 qint64 result = 0;218 219 QFile file("wav.txt");220 file.open(QIODevice::WriteOnly | QIODevice::Text);221 QTextStream stream;222 stream.setDevice(&file);223 224 if (isPCMS16LE(outputFormat) && isPCMS16LE(m_format)) {225 QVector<char> inputSample(2 * m_format.channels());226 227 qint16 *output = reinterpret_cast<qint16*>(buffer.data());228 229 while (result < buffer.size()) {230 if (device.read(inputSample.data(), inputSample.count())) {231 int inputIdx = 0;232 for (int outputIdx = 0; outputIdx < outputFormat.channels(); ++outputIdx) {233 const qint16* input = reinterpret_cast<const qint16*>(inputSample.data() + 2 * inputIdx);234 *output++ = qFromLittleEndian<qint16>(*input);235 result += 2;236 if (inputIdx < m_format.channels())237 ++inputIdx;238 }239 } else {240 break;241 }242 }243 }244 return result;245 }246
Note:
See TracChangeset
for help on using the changeset viewer.