File indexing completed on 2024-04-28 15:08:06

0001 /* GCompris - GSynth.cpp
0002  *
0003  * SPDX-FileCopyrightText: 2018 Timothée Giet <animtim@gmail.com>
0004  *
0005  * Authors:
0006  *   Johnny Jazeix <jazeix@gmail.com>
0007  *   Timothée Giet <animtim@gmail.com>
0008  *
0009  *   SPDX-License-Identifier: GPL-3.0-or-later
0010  */
0011 
0012 #include "GSynth.h"
0013 #include "generator.h"
0014 
0015 #include <QDebug>
0016 #include <QQmlEngine>
0017 
0018 GSynth *GSynth::m_instance = nullptr;
0019 
0020 GSynth::GSynth(QObject *parent) : QObject(parent)
0021 {
0022     static const int bufferSize = 8192;
0023 
0024     m_format.setSampleRate(22050);
0025     m_format.setChannelCount(1);
0026     m_format.setSampleSize(16);
0027     m_format.setCodec("audio/pcm");
0028     m_format.setByteOrder(QAudioFormat::LittleEndian);
0029     m_format.setSampleType(QAudioFormat::SignedInt);
0030 
0031     QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
0032     if (!info.isFormatSupported(m_format)) {
0033         qWarning() << "Default format not supported - trying to use nearest";
0034         m_format = info.nearestFormat(m_format);
0035     }
0036     m_device = QAudioDeviceInfo::defaultOutputDevice();
0037     m_buffer = QByteArray(bufferSize, 0);
0038 
0039     m_audioOutput = new QAudioOutput(m_device, m_format, this);
0040     m_audioOutput->setBufferSize(bufferSize);
0041     m_generator   = new Generator(m_format, this);
0042     // todo Only start generator if musical activity, and stop it on exit (in main.qml, activity.isMusicalActivity)
0043     m_generator->setPreset(PresetCustom);
0044     m_generator->start();
0045     m_audioOutput->start(m_generator);
0046     m_audioOutput->setVolume(1);
0047 }
0048 
0049 GSynth::~GSynth() {
0050     m_audioOutput->stop();
0051     m_generator->stop();
0052     delete m_audioOutput;
0053     delete m_generator;
0054     
0055     auto i = m_timers.constBegin();
0056     while (i != m_timers.constEnd()) {
0057         delete i.value();
0058         ++i;
0059     }
0060 }
0061 
0062 void GSynth::generate(int note, int duration) {
0063     //test part...
0064     m_generator->noteOn(1, note, 255);
0065     if(!m_timers.contains(note)) {
0066         m_timers[note] = new QTimer();
0067         connect(m_timers[note], &QTimer::timeout, this,
0068                 [this, note]() {
0069                     stopAudio(note);
0070                 });
0071     }
0072     m_timers[note]->start(duration);
0073 }
0074 
0075 void GSynth::stopAudio(int note) {
0076     m_generator->noteOff(1, note);
0077 }
0078 
0079 QObject *GSynth::synthProvider(QQmlEngine *engine,
0080                                QJSEngine *scriptEngine)
0081 {
0082     Q_UNUSED(engine)
0083     Q_UNUSED(scriptEngine)
0084 
0085     GSynth* synth = getInstance();
0086     return synth;
0087 }
0088 
0089 #include "moc_GSynth.cpp"