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 }