[AFV] Optimize loading and sharing of CResourceSound objects

- Loading is now happening in a worker to not block the main thhread
- The internal data is shared between all instances of the class.
This commit is contained in:
Roland Rossgotterer
2019-10-02 10:21:29 +02:00
committed by Mat Sutcliffe
parent b65b2caa76
commit ac833910c8
5 changed files with 88 additions and 27 deletions

View File

@@ -12,6 +12,7 @@
#include "audioutilities.h"
#include "blackmisc/fileutils.h"
#include "blackmisc/stringutils.h"
#include <QCoreApplication>
using namespace BlackMisc;
using namespace BlackSound::Wav;
@@ -20,30 +21,53 @@ namespace BlackSound
{
namespace SampleProvider
{
CResourceSound::CResourceSound()
{
m_data = new CResourceSoundData;
}
CResourceSound::CResourceSound(const QString &audioFileName)
{
CWavFile wavFile;
m_fn.clear();
m_samples.clear();
if (wavFile.open(audioFileName))
m_data = new CResourceSoundData;
m_data->fileName = audioFileName;
}
bool CResourceSound::load()
{
if (m_data->fileName.isEmpty()) { return false; }
QObject *parent = QCoreApplication::instance();
Q_ASSERT(parent);
CWorker *worker = CWorker::fromTask(parent, "loadResourceSound", [this]()
{
if (wavFile.fileFormat().sampleType() == QAudioFormat::Float)
CWavFile wavFile;
m_data->samples.clear();
if (wavFile.open(m_data->fileName))
{
// Not implemented
// m_samples = convertFloatBytesTo16BitPCM(wavFile.audioData());
if (wavFile.fileFormat().sampleType() == QAudioFormat::Float)
{
// Not implemented
// m_samples = convertFloatBytesTo16BitPCM(wavFile.audioData());
}
else
{
m_data->samples = convertBytesTo32BitFloatPCM(wavFile.audioData());
}
}
else
{
m_samples = convertBytesTo32BitFloatPCM(wavFile.audioData());
}
m_fn = audioFileName;
}
});
worker->then([this]()
{
m_data->isLoaded = true;
});
return worker ? true : false;
}
bool CResourceSound::isSameFileName(const QString &fn) const
{
if (fn.isEmpty()) { return false; }
return stringCompare(fn, m_fn, CFileUtils::osFileNameCaseSensitivity());
return stringCompare(fn, m_data->fileName, CFileUtils::osFileNameCaseSensitivity());
}
} // ns
} // ns

View File

@@ -13,33 +13,53 @@
#include "blacksound/blacksoundexport.h"
#include "blacksound/wav/wavfile.h"
#include "blackmisc/worker.h"
#include <QString>
#include <QVector>
#include <QExplicitlySharedDataPointer>
#include <atomic>
namespace BlackSound
{
namespace SampleProvider
{
//! CResourceSound shared data
struct CResourceSoundData : public QSharedData
{
QString fileName; //!< file name
bool isLoaded = false; //!< is audio loaded
QVector<float> samples; //!< audio samples
};
//! File from resources
class CResourceSound
{
public:
//! Constructor
CResourceSound();
//! Sound of audio file
CResourceSound(const QString &audioFileName);
//! Load the attached resource file
bool load();
//! Is resource already loaded?
bool isLoaded() { return m_data->isLoaded; }
//! Audio data
const QVector<float> &audioData() const { return m_samples; }
const QVector<float> &audioData() const { return m_data->samples; }
//! Corresponding file
const QString &getFileName() { return m_fn; }
const QString &getFileName() { return m_data->fileName; }
//! Is same file?
bool isSameFileName(const QString &fn) const;
private:
QString m_fn; //!< file name
QVector<float> m_samples;
QExplicitlySharedDataPointer<CResourceSoundData> m_data;
};
} // ns
} // ns

View File

@@ -15,6 +15,8 @@ namespace BlackSound
int CResourceSoundSampleProvider::readSamples(QVector<float> &samples, qint64 count)
{
if (! m_resourceSound.isLoaded()) { return 0; }
if (count > m_tempBufferSize)
{
qDebug() << "Count too large for temp buffer" << count;

View File

@@ -23,11 +23,7 @@ namespace BlackSound
return samples;
}
Samples::Samples() :
m_crackle(CFileUtils::soundFilePathAndFileName(fnCrackle())),
m_click(CFileUtils::soundFilePathAndFileName(fnClick())),
m_whiteNoise(CFileUtils::soundFilePathAndFileName(fnWhiteNoise())),
m_hfWhiteNoise(CFileUtils::soundFilePathAndFileName(fnHfWhiteNoise()))
Samples::Samples()
{
this->initSounds();
}
@@ -36,13 +32,32 @@ namespace BlackSound
{
const CSettings settings = m_audioSettings.get();
QString f = settings.getNotificationFilePath(fnCrackle());
if (!m_crackle.isSameFileName(f)) { m_crackle = CResourceSound(f); }
if (!m_crackle.isSameFileName(f))
{
m_crackle = CResourceSound(f);
m_crackle.load();
}
f = settings.getNotificationFilePath(fnClick());
if (!m_click.isSameFileName(f)) { m_click = CResourceSound(f); }
if (!m_click.isSameFileName(f))
{
m_click = CResourceSound(f);
m_click.load();
}
f = settings.getNotificationFilePath(fnWhiteNoise());
if (!m_whiteNoise.isSameFileName(f)) { m_whiteNoise = CResourceSound(f); }
if (!m_whiteNoise.isSameFileName(f))
{
m_whiteNoise = CResourceSound(f);
m_whiteNoise.load();
}
f = settings.getNotificationFilePath(fnHfWhiteNoise());
if (!m_hfWhiteNoise.isSameFileName(f))
{
m_hfWhiteNoise = CResourceSound(f);
m_hfWhiteNoise.load();
}
}
void Samples::onSettingsChanged()

View File

@@ -36,7 +36,7 @@ namespace BlackSound
const CResourceSound &crackle() const { return m_crackle; }
const CResourceSound &click() const { return m_click; }
const CResourceSound &whiteNoise() const { return m_whiteNoise; }
const CResourceSound hfWhiteNoise() const { return m_hfWhiteNoise; }
const CResourceSound &hfWhiteNoise() const { return m_hfWhiteNoise; }
//! @}
//! Play the click sound