File indexing completed on 2024-11-10 05:11:08
0001 /* 0002 * Copyright 2023 by Aditya Mehra <aix.m@outlook.com> 0003 * 0004 * Licensed under the Apache License, Version 2.0 (the "License"); 0005 * you may not use this file except in compliance with the License. 0006 * You may obtain a copy of the License at 0007 * 0008 * http://www.apache.org/licenses/LICENSE-2.0 0009 * 0010 * Unless required by applicable law or agreed to in writing, software 0011 * distributed under the License is distributed on an "AS IS" BASIS, 0012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 0013 * See the License for the specific language governing permissions and 0014 * limitations under the License. 0015 * 0016 */ 0017 0018 #include "audiostreamdevice.h" 0019 #include <QUrl> 0020 #include <QFile> 0021 0022 AudioStreamDevice::AudioStreamDevice(QObject *parent): 0023 m_input(&m_data), 0024 m_output(&m_data), 0025 m_state(State::Stopped) 0026 { 0027 setOpenMode(QIODevice::ReadOnly); 0028 0029 isInited = false; 0030 isDecodingFinished = false; 0031 calculator = new FFTCalc(this); 0032 connect(calculator, &FFTCalc::calculatedSpectrum, this, [this](QVector<double> spectrum) { 0033 int size = 20; 0034 m_spectrum.resize(size); 0035 int j = 0; 0036 for (int i = 0; i < spectrum.size(); i += spectrum.size()/(size - 1)) { 0037 m_spectrum[j] = spectrum[i]; 0038 ++j; 0039 } 0040 emit spectrumChanged(m_spectrum); 0041 }); 0042 connect(&m_decoder, QOverload<QAudioDecoder::Error>::of(&QAudioDecoder::error), this, &AudioStreamDevice::handleError); 0043 } 0044 0045 bool AudioStreamDevice::uninit() 0046 { 0047 if (isInited) 0048 { 0049 m_decoder.stop(); 0050 m_input.reset(); 0051 m_output.reset(); 0052 m_data.clear(); 0053 m_spectrum.clear(); 0054 isInited = false; 0055 isDecodingFinished = false; 0056 return true; 0057 } 0058 return false; 0059 } 0060 0061 bool AudioStreamDevice::init(const QAudioFormat& format) 0062 { 0063 m_format = format; 0064 m_decoder.setAudioFormat(m_format); 0065 0066 connect(&m_decoder, SIGNAL(bufferReady()), this, SLOT(bufferReady())); 0067 connect(&m_decoder, SIGNAL(finished()), this, SLOT(finished())); 0068 0069 if (!m_output.open(QIODevice::ReadOnly) || !m_input.open(QIODevice::WriteOnly)) 0070 { 0071 return false; 0072 } 0073 0074 isInited = true; 0075 0076 return true; 0077 } 0078 0079 qint64 AudioStreamDevice::readData(char* data, qint64 maxlen) 0080 { 0081 memset(data, 0, maxlen); 0082 0083 if (m_state == State::Playing) 0084 { 0085 m_output.read(data, maxlen); 0086 0087 if (maxlen > 0) 0088 { 0089 QByteArray buff(data, maxlen); 0090 emit newData(buff); 0091 QAudioBuffer buffer(buff, m_format); 0092 calculateSpectrum(buffer); 0093 emit positionChanged(m_output.pos()); 0094 } 0095 0096 if (atEnd()) 0097 { 0098 stop(); 0099 emit endOfMedia(); 0100 } 0101 } 0102 0103 return maxlen; 0104 } 0105 0106 qint64 AudioStreamDevice::writeData(const char* data, qint64 len) 0107 { 0108 Q_UNUSED(data); 0109 Q_UNUSED(len); 0110 0111 return 0; 0112 } 0113 0114 void AudioStreamDevice::play(const QUrl &file) 0115 { 0116 clear(); 0117 m_decoder.setSource(file); 0118 m_decoder.start(); 0119 qDebug() << "m_decoder started"; 0120 m_state = State::Playing; 0121 emit stateChanged(m_state); 0122 } 0123 0124 void AudioStreamDevice::stop() 0125 { 0126 clear(); 0127 m_state = State::Stopped; 0128 emit stateChanged(m_state); 0129 } 0130 0131 0132 void AudioStreamDevice::clear() 0133 { 0134 m_decoder.stop(); 0135 m_data.clear(); 0136 isDecodingFinished = false; 0137 qDebug() << "In Clear Decoder"; 0138 } 0139 0140 bool AudioStreamDevice::atEnd() const 0141 { 0142 return m_output.size() 0143 && m_output.atEnd() 0144 && isDecodingFinished; 0145 } 0146 0147 void AudioStreamDevice::bufferReady() 0148 { 0149 const QAudioBuffer &buffer = m_decoder.read(); 0150 0151 const int length = buffer.byteCount(); 0152 const char *data = buffer.constData<char>(); 0153 0154 m_input.write(data, length); 0155 } 0156 0157 void AudioStreamDevice::finished() 0158 { 0159 isDecodingFinished = true; 0160 emit durationChanged(m_output.size()); 0161 if(m_output.size() == m_input.size()) { 0162 emit bufferedMedia(); 0163 } 0164 } 0165 0166 QVector<double> AudioStreamDevice::spectrum() const 0167 { 0168 return m_spectrum; 0169 } 0170 0171 0172 void AudioStreamDevice::calculateSpectrum(QAudioBuffer buffer) 0173 { 0174 qreal peakValue; 0175 int duration; 0176 0177 if(buffer.frameCount() < 512) 0178 return; 0179 0180 levelLeft = levelRight = 0; 0181 0182 if(buffer.format().channelCount() != 2) 0183 return; 0184 0185 sample.resize(buffer.frameCount()); 0186 if(buffer.format().sampleFormat() == QAudioFormat::UInt8){ 0187 QAudioBuffer::S16S *data = (QAudioBuffer::S16S *)buffer.constData<char>(); 0188 peakValue=UINT8_MAX/2; 0189 for(int i=0; i<buffer.frameCount(); i++){ 0190 sample[i] = data[i].value(QAudioFormat::FrontLeft) / peakValue; 0191 levelLeft += data[i].value(QAudioFormat::FrontLeft); 0192 levelRight += data[i].value(QAudioFormat::FrontRight); 0193 } 0194 } else if(buffer.format().sampleFormat() == QAudioFormat::Int16){ 0195 QAudioBuffer::S16S *data = (QAudioBuffer::S16S *)buffer.constData<char>(); 0196 peakValue=INT16_MAX; 0197 for(int i=0; i<buffer.frameCount(); i++){ 0198 sample[i] = data[i].value(QAudioFormat::FrontLeft) / peakValue; 0199 levelLeft += data[i].value(QAudioFormat::FrontLeft); 0200 levelRight += data[i].value(QAudioFormat::FrontRight); 0201 } 0202 } else if(buffer.format().sampleFormat() == QAudioFormat::Int32){ 0203 QAudioBuffer::S32S *data = (QAudioBuffer::S32S *)buffer.constData<char>(); 0204 peakValue=INT32_MAX; 0205 for(int i=0; i<buffer.frameCount(); i++){ 0206 sample[i] = data[i].value(QAudioFormat::FrontLeft) / peakValue; 0207 levelLeft += data[i].value(QAudioFormat::FrontLeft); 0208 levelRight += data[i].value(QAudioFormat::FrontRight); 0209 } 0210 } else if(buffer.format().sampleFormat() == QAudioFormat::Float){ 0211 QAudioBuffer::F32S *data = (QAudioBuffer::F32S *)buffer.constData<char>(); 0212 peakValue=1.0; 0213 for(int i=0; i<buffer.frameCount(); i++){ 0214 sample[i] = data[i].value(QAudioFormat::FrontLeft) / peakValue; 0215 levelLeft += data[i].value(QAudioFormat::FrontLeft); 0216 levelRight += data[i].value(QAudioFormat::FrontRight); 0217 } 0218 } else { 0219 return; 0220 } 0221 0222 duration = buffer.format().durationForBytes(buffer.frameCount())/1000; 0223 calculator->calc(sample, duration); 0224 emit levels(levelLeft/buffer.frameCount(), levelRight/buffer.frameCount()); 0225 } 0226 0227 qint64 AudioStreamDevice::duration() const 0228 { 0229 return m_output.size(); 0230 } 0231 0232 qint64 AudioStreamDevice::position() const 0233 { 0234 return m_output.pos(); 0235 } 0236 0237 void AudioStreamDevice::seekFrom(qint64 position) 0238 { 0239 m_output.seek(position); 0240 } 0241 0242 void AudioStreamDevice::handleError(QAudioDecoder::Error error) 0243 { 0244 qDebug() << "Error: " << error; 0245 }