File indexing completed on 2024-05-12 17:21:22

0001 /*
0002  * SPDX-FileCopyrightText: 2020 Jonah BrĂ¼chert <jbb@kaidan.im>
0003  * SPDX-FileCopyrightText: 2020-2021 Devin Lin <espidev@gmail.com>
0004  *
0005  * SPDX-License-Identifier: GPL-3.0-or-later
0006  */
0007 
0008 #include <QAudioFormat>
0009 #include <QAudioInput>
0010 #include <QMediaCaptureSession>
0011 
0012 #include "audioprober.h"
0013 
0014 AudioProber::AudioProber(QObject *parent)
0015     : QAudioDecoder{ parent }
0016 {}
0017 
0018 AudioProber::AudioProber(QObject *parent, QMediaRecorder *source)
0019     : QAudioDecoder{ parent }
0020     , m_recorderSource{ source }
0021 {
0022     QAudioFormat format;
0023     // Set up the desired format, for example:
0024     format.setSampleRate(8000);
0025     format.setChannelCount(1);
0026     format.setSampleFormat(QAudioFormat::UInt8);
0027 
0028     QAudioDevice device = source->captureSession()->audioInput()->device();
0029     if (!device.isFormatSupported(format)) {
0030         qWarning() << "Default format not supported, trying to use the nearest.";
0031     }
0032 
0033     m_audioSource = new QAudioSource(device, format, this);
0034 
0035     // connect to recorder
0036     connect(m_recorderSource, &QMediaRecorder::recorderStateChanged, this, &AudioProber::handleRecorderState);
0037     
0038     // loop to add volume bars 
0039     volumeBarTimer = new QTimer(this);
0040     connect(volumeBarTimer, &QTimer::timeout, this, &AudioProber::processVolumeBar);
0041     volumeBarTimer->setInterval(150);
0042 }
0043 
0044 AudioProber::AudioProber(QObject *parent, QMediaPlayer *source) 
0045     : QAudioDecoder{ parent }
0046     , m_playerSource{ source }
0047 {
0048     connect(this, &AudioProber::bufferReady, this, &AudioProber::process);
0049     
0050     // connect to player
0051     connect(m_playerSource, &QMediaPlayer::playbackStateChanged, this, &AudioProber::handlePlayerState);
0052     
0053     // loop to add volume bars 
0054     volumeBarTimer = new QTimer(this);
0055     connect(volumeBarTimer, &QTimer::timeout, this, &AudioProber::processVolumeBar);
0056     volumeBarTimer->setInterval(150);
0057 }
0058 
0059 void AudioProber::handleRecorderState(QMediaRecorder::RecorderState state) {
0060     if (state == QMediaRecorder::RecordingState) {
0061         start();
0062         volumeBarTimer->start();
0063     } else if (state == QMediaRecorder::PausedState) {
0064         stop();
0065         volumeBarTimer->stop();
0066     } else if (state == QMediaRecorder::StoppedState) {
0067         stop();
0068         volumeBarTimer->stop();
0069         // clear volumes list
0070         clearVolumesList();
0071     }
0072 }
0073 
0074 void AudioProber::handlePlayerState(QMediaPlayer::PlaybackState state) {
0075     if (state == QMediaPlayer::PlayingState) {
0076         volumeBarTimer->start();
0077     } else if (state == QMediaPlayer::PausedState) {
0078         volumeBarTimer->stop();
0079     } else if (state == QMediaPlayer::StoppedState) {
0080         volumeBarTimer->stop();
0081         // clear volumes list
0082         clearVolumesList();
0083     }
0084 }
0085 
0086 void AudioProber::start()
0087 {
0088     qDebug() << "pang";
0089     QIODevice *iodevice = m_audioSource->start();
0090     qDebug() << iodevice;
0091     setSourceDevice(iodevice);
0092     qDebug() << sourceDevice();
0093     QAudioDecoder::start();
0094     connect(this, &QAudioDecoder::bufferReady, this, &AudioProber::process);
0095 }
0096 
0097 void AudioProber::processVolumeBar() 
0098 {
0099     if (isDecoding()) {
0100         // m_audioLen might be 0
0101         const int val = m_audioLen == 0 ? 0 : m_audioSum / m_audioLen;
0102 
0103         m_volumesList.append(val);
0104         Q_EMIT volumesListAdded(val);
0105         
0106         if (m_volumesList.count() > m_maxVolumes) {
0107             m_volumesList.removeFirst();
0108         }
0109 
0110         Q_EMIT volumesListChanged();
0111 
0112         // index of rectangle to animate
0113         if (m_volumesList.count() != 0) {
0114             m_animationIndex = m_volumesList.count();
0115             Q_EMIT animationIndexChanged();
0116         }
0117 
0118         m_audioSum = 0;
0119         m_audioLen = 0;
0120     }
0121 }
0122 
0123 void AudioProber::process()
0124 {
0125     qDebug() << "ping";
0126     int sum = 0;
0127     auto buffer = read();
0128     for (int i = 0; i < buffer.sampleCount(); i++) {
0129         const short *bufferData = buffer.data<short>();
0130         sum += abs(bufferData[i]);
0131     }
0132 
0133     sum /= read().sampleCount();
0134     
0135     m_audioSum += sum;
0136     m_audioLen++;
0137 }
0138 
0139 QVariantList AudioProber::volumesList() const
0140 {
0141     return m_volumesList;
0142 }
0143 
0144 int AudioProber::maxVolumes()
0145 {
0146     return m_maxVolumes;
0147 }
0148 
0149 void AudioProber::setMaxVolumes(int m)
0150 {
0151     m_maxVolumes = m;
0152     Q_EMIT maxVolumesChanged();
0153 }
0154 
0155 int AudioProber::animationIndex()
0156 {
0157     return m_animationIndex;
0158 }
0159 
0160 void AudioProber::clearVolumesList()
0161 {
0162     while (!m_volumesList.empty())
0163         m_volumesList.removeFirst();
0164     Q_EMIT volumesListChanged();
0165     Q_EMIT volumesListCleared();
0166 }