Ignore:
Timestamp:
May 5, 2011, 5:36:53 AM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/demos/spectrum/app/wavfile.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 201 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation ([email protected])
     
    7777    RIFFHeader  riff;
    7878    WAVEHeader  wave;
    79     DATAHeader  data;
    8079};
    8180
    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)
     81WavFile::WavFile(QObject *parent)
     82    : QFile(parent)
     83    , m_headerLength(0)
    8884{
    8985
    9086}
    9187
    92 bool WavFile::readHeader(QIODevice &device)
     88bool WavFile::e)
    9389{
    94     bool result = true;
     90    close();
     91    setFileName(fileName);
     92    return QFile::open(QIODevice::ReadOnly) && readHeader();
     93}
    9594
    96     if (!device.isSequential())
    97         result = device.seek(0);
    98     // else, assume that current position is the start of the header
     95const QAudioFormat &WavFile::fileFormat() const
     96{
     97    return m_fileFormat;
     98}
    9999
     100
     101
     102
     103
     104
     105
     106
     107
     108
     109
    100110    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)) {
    114116
    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;
    119119
    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            }
    130129
    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;
    135147        }
    136148    }
    137 
     149    m_headerLength = pos();
    138150    return result;
    139151}
    140 
    141 bool WavFile::writeHeader(QIODevice &device)
    142 {
    143     CombinedHeader header;
    144 
    145     memset(&header, 0, HeaderLength);
    146 
    147     // RIFF header
    148     if (m_format.byteOrder() == QAudioFormat::LittleEndian)
    149         strncpy(&header.riff.descriptor.id[0], "RIFF", 4);
    150     else
    151         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 header
    157     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 header
    174     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() const
    182 {
    183     return m_format;
    184 }
    185 
    186 qint64 WavFile::dataLength() const
    187 {
    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.