Commit 3001660b authored by Leander Schulten's avatar Leander Schulten

Aubio: Use aubio and not AudioFFT to generate a spectrum/frequency domain...

Aubio: Use aubio and not AudioFFT to generate a spectrum/frequency domain analysis. Remove AudioFFT from the Lichtsteuerung
parent a014e441
Pipeline #204566 passed with stage
in 5 minutes and 14 seconds
......@@ -36,10 +36,7 @@ Die Lichtsteuerung hängt von ein paar anderen Projekten ab.
Boost wird benötigt, um bei Modules nicht lineare Codeausführung zu ermöglichen (Corotines) und wird genutzt, um Stacktraces auszugeben.
#### [RtAudio](https://github.com/thestk/rtaudio)
RtAudio (Realtime Audio) ist eine Bibliothek, mit welcher auf jedem Betriebsystem alle Audioeingänge aufgenommen werden können. Unter Windows ist es auch möglich den Audio Ausgang aufzunehmen. Vor RtAudio wurde diese Aufgabe von der [Capture_Windows_SoundOutput](https://git.rwth-aachen.de/leander.schulten/Capture_Windows_SoundOutput) lib übernommen (Diese konnte nur unter Windows den Standardausgang aufnehmen).
#### [AudioFFT](https://git.rwth-aachen.de/leander.schulten/FFT_for_Audio)
Dieses Projekt ermöglicht es, den abgefangenen Sound auf Frequenzbereiche aufzuspalten, wobei jedem Frequenzbereich eine "Energie"/Stärke zugeordnet wird. Dieses Projekt hängt wiederum von [fftw](http://www.fftw.org/) ab. Diese Abhängigkeiten befinden sich auch hier als kompilierte lib im git.
RtAudio (Realtime Audio) ist eine Bibliothek, mit welcher auf jedem Betriebsystem alle Audioeingänge aufgenommen werden können. Unter Windows ist es auch möglich den Audio Ausgang aufzunehmen. Vor RtAudio wurde diese Aufgabe von der [Capture_Windows_SoundOutput](https://git.rwth-aachen.de/leander.schulten/Capture_Windows_SoundOutput) lib übernommen (Diese konnte nur unter Windows den Standardausgang aufnehmen).
#### [SusbDmx-Driver](https://git.rwth-aachen.de/leander.schulten/SusbDMX-Driver)
Dieses Projekt enthält den aktuellen Treiber, der es ermöglicht, den USB zu DMX Konverter anzusteuern. Dieser Treiber befindet sich nicht als lib hier im git.
......
......@@ -55,12 +55,6 @@ fi
# copy aubio
cp "src/lib/aubio/lib/libaubio-5.dll" "$target_folder"
#copy AudioFFT
cp "src/lib/AudioFFT/dll/win${bit}/AudioFFT.dll" "$target_folder"
cp "src/lib/AudioFFT/dll/win${bit}/libfftw3-3.dll" "$target_folder"
cp "src/lib/AudioFFT/dll/win${bit}/libfftw3f-3.dll" "$target_folder"
cp "src/lib/AudioFFT/dll/win${bit}/libfftw3l-3.dll" "$target_folder"
#copy DrMinGw
if [[ $bit == "64" ]]; then
for file in src/lib/DrMinGW/bin/*; do cp "$file" "$target_folder";done
......
......@@ -20,6 +20,7 @@ SOURCES += \
applicationdata.cpp \
audio/aubio/aubiocapi.cpp \
audio/aubio/onsetanalysis.cpp \
audio/aubio/spectrumanalysis.cpp \
audio/aubio/tempoanalysis.cpp \
audio/audioeventdata.cpp \
audio/remotevolume.cpp \
......@@ -107,6 +108,7 @@ DEFINES += _USE_MATH_DEFINES
HEADERS += \
audio/aubio/aubiocapi.h \
audio/aubio/onsetanalysis.h \
audio/aubio/spectrumanalysis.h \
audio/aubio/tempoanalysis.h \
audio/audioeventdata.h \
audio/remotevolume.h \
......@@ -226,23 +228,6 @@ macx{
INCLUDEPATH += /usr/local/include
}
macx{
#AudioFFT
LIBS += -L$$PWD/'lib/AudioFFT/dll' -lAudioFFT
INCLUDEPATH += $$PWD/lib/AudioFFT/include
}
win32-g++{
#AudioFFT
#LIBS += -L$$PWD/'lib/AudioFFT/dll' -lAudioFFT
contains(QT_ARCH, i386){ # 32 bit
LIBS += -L$$PWD/'lib/AudioFFT/dll/win32/' -lAudioFFT
} else { # 64 bit
LIBS += -L$$PWD/'lib/AudioFFT/dll/win64' -lAudioFFT
}
INCLUDEPATH += $$PWD/'lib/AudioFFT/include'
}
win32-g++{
#DrMinGW
#LIBS += -L$$PWD/'lib/AudioFFT/dll' -lAudioFFT
......@@ -279,12 +264,6 @@ macx{
DEFINES += _GNU_SOURCE
}
win32-msvc{
#AudioFFT
LIBS += -L$$PWD/'lib/AudioFFT/dll/AudioFFT.dll'
INCLUDEPATH += $$PWD/'lib/AudioFFT/include'
}
# RTAudio
INCLUDEPATH += $$PWD/lib/RtAudio/include
LIBS += -L$$PWD/lib/RtAudio/lib -lrtaudio
......
#include "spectrumanalysis.h"
namespace Audio::Aubio {
using namespace C_API;
SpectrumAnalysis::SpectrumAnalysis(C_API::uint_t spectrumSize, C_API::uint_t stepSize) : spectrumAnalyser(new_aubio_pvoc(spectrumSize * 2, stepSize), del_aubio_pvoc), fftOutputData(new_cvec(spectrumSize * 2), del_cvec), inputData{stepSize, nullptr} {}
void SpectrumAnalysis::processNewSamples(float *newSamples) {
inputData.data = newSamples;
aubio_pvoc_do(spectrumAnalyser.get(), &inputData, fftOutputData.get());
}
boost::beast::span<float> SpectrumAnalysis::getSpectrum() const {
return {fftOutputData->norm, fftOutputData->length};
}
float *SpectrumAnalysis::getPointerToSpectrum() const {
return fftOutputData->norm;
}
} // namespace Audio::Aubio
#ifndef SPECTRUMANALYSIS_H
#define SPECTRUMANALYSIS_H
#include "aubiocapi.h"
#include <boost/beast/core/span.hpp> // TODO use std::span in c++20
#include <memory>
namespace Audio::Aubio {
/**
* @brief The SpectrumAnalysis class computes a spectrum (energy for every frequency) for the audio data.
*/
class SpectrumAnalysis {
std::unique_ptr<C_API::aubio_pvoc_t, decltype(&C_API::del_aubio_pvoc)> spectrumAnalyser;
std::unique_ptr<C_API::cvec_t, decltype(&C_API::del_cvec)> fftOutputData;
C_API::fvec_t inputData;
public:
/**
* @brief SpectrumAnalysis Creates a spectrum analysis.
* @param spectrumSize The size of blocks in the spectrum from 0 to sampleRate/2. Must be a power of 2.
* @param stepSize The size of a new block that gets passed to this->processNewSamples().
*/
SpectrumAnalysis(C_API::uint_t spectrumSize, C_API::uint_t stepSize);
/**
* @brief processNewSamples process and analyse new samples
* @param newSamples A pointer to the new samples, the length of the array must be minimun the step size from the constructor
*/
void processNewSamples(float *newSamples);
/**
* @brief getSpectrum returns the spectrum (the enery for every block)
* @return the spectrum
*/
[[nodiscard]] boost::beast::span<float> getSpectrum() const;
/**
* @brief getPointerToSpectrum See getSpectrum().
* @return A pointer to the spectrum. You can modify the values. They will be overwritten in the processNewSamples(float*) method
*/
[[nodiscard]] float *getPointerToSpectrum() const; // remove when using std::span in c++20
};
} // namespace Audio::Aubio
#endif // SPECTRUMANALYSIS_H
......@@ -16,8 +16,8 @@
#endif
namespace Audio {
AudioCaptureManager::AudioCaptureManager():audiofft(sample.size())
{
AudioCaptureManager::AudioCaptureManager() {
rtAudio.showWarnings();
updateCaptureDeviceList();
}
......@@ -35,6 +35,7 @@ void AudioCaptureManager::initCallback(int channels, int samplesPerSecond) {
if (GUI::Colorplot::getLast()) {
GUI::Colorplot::getLast()->setBlockSize(512);
}
spectrumAnalysis.emplace(2048, samplesPerFrame);
}
void AudioCaptureManager::dataCallback(float* data, unsigned int frames, bool*done){
......@@ -58,7 +59,6 @@ void AudioCaptureManager::dataCallback(float* data, unsigned int frames, bool*do
sample.addData(data,data+frames*static_cast<unsigned>(channels),channels-1,firstIndex);
audiofft.analyse(sample.data(),1,fftoutput.data());
{
// feed the *analysis classes with new samples
int restFrames = static_cast<int>(frames);
......@@ -75,6 +75,7 @@ void AudioCaptureManager::dataCallback(float* data, unsigned int frames, bool*do
restFrames -= samplesPerFrame;
continue;
}
spectrumAnalysis->processNewSamples(sample.data() + sample.size() - restFrames);
for (auto &[onsetFunction, pair] : onsetAnalyzes) {
bool wasOnset = pair.first.processNewSamples(sample.data() + sample.size() - restFrames);
pair.second.addOnsetData(pair.second.getNewestSample(), pair.first.getOnsetValue(), 0);
......@@ -95,15 +96,16 @@ void AudioCaptureManager::dataCallback(float* data, unsigned int frames, bool*do
}
}
// db scale
std::transform(fftoutput.begin(), fftoutput.end(), fftoutput.begin(), [](auto i) { return 10 * std::log10(1 + i); });
auto spectrum = spectrumAnalysis->getSpectrum();
std::transform(spectrum.cbegin(), spectrum.cend(), spectrumAnalysis->getPointerToSpectrum(), [](auto i) { return 10 * std::log10(1 + i); });
if (GUI::Graph::getLast() && run) {
GUI::Graph::getLast()->showData(fftoutput.data(), fftoutput.size());
GUI::Graph::getLast()->showData(spectrumAnalysis->getPointerToSpectrum(), spectrum.size());
}
if (GUI::Colorplot::getLast() && run) {
GUI::Colorplot::getLast()->startBlock();
for (int i = 0; i < 512; ++i) {
GUI::Colorplot::getLast()->pushDataToBlock(fftoutput.at(i));
GUI::Colorplot::getLast()->pushDataToBlock(spectrum.begin()[i]);
}
GUI::Colorplot::getLast()->endBlock();
}
......
......@@ -5,9 +5,10 @@
#include "modelvector.h"
#include "sample.h"
#include "aubio/onsetanalysis.h"
#include "aubio/spectrumanalysis.h"
#include "aubio/tempoanalysis.h"
#include "audio_fft.h"
#include <RtAudio.h>
#include <boost/beast/core/span.hpp> // TODO use std::span in c++20
#include <map>
#include <thread>
......@@ -35,12 +36,12 @@ class AudioCaptureManager : public QObject
Q_PROPERTY(int currentCaptureDevice READ getCurrentCaptureDevice WRITE setCurrentCaptureDevice NOTIFY currentCaptureDeviceChanged)
Q_PROPERTY(QAbstractItemModel *captureDeviceNames READ getCaptureDeviceNamesModel CONSTANT)
Sample<float,4096> sample;
std::array<float, 2048> fftoutput;
std::atomic_bool run;
int currentCaptureDevice = -1;
RtAudio rtAudio;
AudioFFT audiofft;
ModelVector<QString> captureDeviceNames;
// we use a optional to delay the creation of the object until we know the samplesPerFrame value
std::optional<Aubio::SpectrumAnalysis> spectrumAnalysis;
int channels = -1;
int samplesPerSecond = -1;
......@@ -105,7 +106,7 @@ public:
*/
const std::vector<QString> &getCaptureDeviceNames() const { return captureDeviceNames.getVector(); }
const std::array<float, 2048> &getFFTOutput() { return fftoutput; }
boost::beast::span<float> getFFTOutput() { return (spectrumAnalysis ? spectrumAnalysis->getSpectrum() : boost::beast::span<float>{nullptr, 0}); }
/**
* @brief requestTempoAnalysis requests the data series from a tempo analysis that uses a spezific onset detection function
* You can call the function with the same parameters multiple times, the result will be the same
......
libAudioFFT.1.0.0.dylib
\ No newline at end of file
libAudioFFT.1.0.0.dylib
\ No newline at end of file
libAudioFFT.1.0.0.dylib
\ No newline at end of file
#ifndef AUDIO_FFT_H
#define AUDIO_FFT_H
#include "audio_fft_global.h"
#include "fftw3.h"
class AUDIO_FFT_SHARED_EXPORT AudioFFT
{
fftw_plan plan;
fftw_complex *in, *out;
const unsigned int size;
public:
AudioFFT(const unsigned int size);
void execute();
void analyse(float* floatData,const int stepsToNext, float*output);
void fillInputData(float* floatData,const int stepsToNext);
void fillInputDataAndApplyHannWindow(float* floatData,const int stepsToNext);
fftw_complex * getInput(){return in;}
fftw_complex * getOutput(){return out;}
/**
* @brief fillOutput füllt size/2 mem positionen mit dem Ergebnis der Analyse in log db scale
* @param mem Ein size/2 langer float array der mit dem Ergebnis gefüllt wird
*/
void fillOutput(float * mem);
unsigned int getSize(){return size;}
~AudioFFT();
private:
void createPlan();
inline float hann(int n);
};
#endif // AUDIO_FFT_H
#ifndef AUDIO_FFT_GLOBAL_H
#define AUDIO_FFT_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(AUDIO_FFT_LIBRARY)
# define AUDIO_FFT_SHARED_EXPORT Q_DECL_EXPORT
#else
# define AUDIO_FFT_SHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // AUDIO_FFT_GLOBAL_H
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment