File indexing completed on 2024-04-14 04:43:18

0001 /* AUDEX CDDA EXTRACTOR
0002  * SPDX-FileCopyrightText: Copyright (C) 2007 Marco Nelles
0003  * <https://userbase.kde.org/Audex>
0004  *
0005  * SPDX-License-Identifier: GPL-3.0-or-later
0006  */
0007 
0008 #include "wavefilewriter.h"
0009 
0010 #include <QDebug>
0011 
0012 WaveFileWriter::WaveFileWriter()
0013 {
0014     p_data_written = 0;
0015     p_endianess = LittleEndian;
0016 }
0017 
0018 WaveFileWriter::~WaveFileWriter()
0019 {
0020     close();
0021 }
0022 
0023 bool WaveFileWriter::open(const QString &filename)
0024 {
0025     close();
0026 
0027     p_data_written = 0;
0028 
0029     p_output_file.setFileName(filename);
0030     if (p_output_file.open(QIODevice::WriteOnly)) {
0031         p_filename = filename;
0032         p_write_empty_header();
0033         return true;
0034     } else {
0035         return false;
0036     }
0037 }
0038 
0039 bool WaveFileWriter::isOpen()
0040 {
0041     return p_output_file.isOpen();
0042 }
0043 
0044 QString WaveFileWriter::filename() const
0045 {
0046     return p_filename;
0047 }
0048 
0049 void WaveFileWriter::setEndianess(const Endianess e)
0050 {
0051     p_endianess = e;
0052 }
0053 
0054 WaveFileWriter::Endianess WaveFileWriter::endianess()
0055 {
0056     return p_endianess;
0057 }
0058 
0059 void WaveFileWriter::close()
0060 {
0061     if (isOpen()) {
0062         if (p_data_written) {
0063             // update wave header
0064             p_update_header();
0065             p_output_file.close();
0066         } else {
0067             p_output_file.close();
0068             p_output_file.remove();
0069         }
0070     }
0071     p_filename.clear();
0072 }
0073 
0074 void WaveFileWriter::write(const QByteArray &data)
0075 {
0076     int len = data.size();
0077     if (isOpen()) {
0078         if (p_endianess == LittleEndian) {
0079             qint64 ret = p_output_file.write(data);
0080             if (ret == -1) {
0081                 Q_EMIT error(p_output_file.errorString());
0082                 return;
0083             }
0084         } else {
0085             if (data.size() % 2 > 0) {
0086                 qDebug() << "Data length is not a multiple of 2! Cannot write data.";
0087                 return;
0088             }
0089             // we need to swap the bytes
0090             char *buffer = new char[len];
0091             for (int i = 0; i < len - 1; i += 2) {
0092                 buffer[i] = data.data()[i + 1];
0093                 buffer[i + 1] = data.data()[i];
0094             }
0095             p_output_file.write(buffer, len);
0096             delete[] buffer;
0097         }
0098         p_data_written += len;
0099     }
0100 }
0101 
0102 void WaveFileWriter::p_write_empty_header()
0103 {
0104     static const unsigned char riffHeader[] = {
0105         0x52, 0x49, 0x46, 0x46, // 0  "RIFF"
0106         0x00, 0x00, 0x00, 0x00, // 4  wavSize
0107         0x57, 0x41, 0x56, 0x45, // 8  "WAVE"
0108         0x66, 0x6d, 0x74, 0x20, // 12 "fmt "
0109         0x10, 0x00, 0x00, 0x00, // 16
0110         0x01, 0x00, 0x02, 0x00, // 20
0111         0x44, 0xac, 0x00, 0x00, // 24
0112         0x10, 0xb1, 0x02, 0x00, // 28
0113         0x04, 0x00, 0x10, 0x00, // 32
0114         0x64, 0x61, 0x74, 0x61, // 36 "data"
0115         0x00, 0x00, 0x00, 0x00  // 40 byteCount
0116     };
0117     p_output_file.write((char *)riffHeader, 44);
0118 }
0119 
0120 void WaveFileWriter::p_update_header()
0121 {
0122     if (isOpen()) {
0123         p_output_file.flush();
0124 
0125         char c[4];
0126         qint32 wavSize = p_data_written + 44 - 8;
0127 
0128         // jump to the wavSize position in the header
0129 
0130         p_output_file.seek(4);
0131         c[0] = (wavSize >> 0) & 0xff;
0132         c[1] = (wavSize >> 8) & 0xff;
0133         c[2] = (wavSize >> 16) & 0xff;
0134         c[3] = (wavSize >> 24) & 0xff;
0135         p_output_file.write(c, 4);
0136 
0137         p_output_file.seek(40);
0138         c[0] = (p_data_written >> 0) & 0xff;
0139         c[1] = (p_data_written >> 8) & 0xff;
0140         c[2] = (p_data_written >> 16) & 0xff;
0141         c[3] = (p_data_written >> 24) & 0xff;
0142         p_output_file.write(c, 4);
0143 
0144         // jump back to the end
0145         p_output_file.seek(p_output_file.size());
0146     }
0147 }