Commit 7d7590dc authored by Leander Schulten's avatar Leander Schulten
Browse files

Merge branch 'QT_QUICK_APP' into CorotineLoopProgramm

# Conflicts:
#	Lichtsteuerung.pro
#	main.cpp
#	main.qml
#	polygon.cpp
#	settings.h
parents 6331f706 fc235ac1
......@@ -68,6 +68,5 @@ Thumbs.db
# Binaries
# --------
*.dll
*.exe
......@@ -59,7 +59,10 @@ SOURCES += \
codeeditorhelper.cpp \
test/testmodulecontroller.cpp \
test/testprogrammblock.cpp \
programblockeditor.cpp
programblockeditor.cpp \
audio/sample.cpp \
test/testsampleclass.cpp \
audio/audiocapturemanager.cpp
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked deprecated (the exact warnings
......@@ -125,7 +128,10 @@ HEADERS += \
programms/program.hpp \
test/testmodulecontroller.h \
test/testprogrammblock.h \
programblockeditor.h
programblockeditor.h \
audio/sample.h \
test/testsampleclass.h \
audio/audiocapturemanager.h
# Default rules for deployment.
......@@ -154,3 +160,28 @@ unix{
#installed with brew install boost
LIBS += -L/usr/local/lib -lboost_coroutine -lboost_context-mt
}
win32-msvc{
LIBS += -L$$PWD/lib/boost/
}
macx{
#AudioFFT
LIBS += -L$$PWD/'lib/AudioFFT/dll' -lAudioFFT.1
INCLUDEPATH += $$PWD/'lib/AudioFFT/include'
#https://forum.qt.io/topic/59209/solved-osx-deployment-fatal-error-with-dylib-library-not-loaded-image-not-found/4
Resources.files += libAudioFFT.1.dylib
Resources.path = Contents/MacOS
QMAKE_BUNDLE_DATA += Resources
}
win32-g++{
#AudioFFT
LIBS += -L$$PWD/'lib/AudioFFT/dll' -lAudioFFT
INCLUDEPATH += $$PWD/'lib/AudioFFT/include'
}
win32-msvc{
#AudioFFT
LIBS += -L$$PWD/'lib/AudioFFT/dll/AudioFFT.dll'
INCLUDEPATH += $$PWD/'lib/AudioFFT/include'
}
#include "audiocapturemanager.h"
#include "graph.h"
#include "colorplot.h"
#include "oscillogram.h"
#include <algorithm>
namespace Audio {
AudioCaptureManager::AudioCaptureManager():audiofft(sample.size())
{
}
void AudioCaptureManager::initCallback(int channels){
this->channels = channels;
if(Colorplot::getLast())
Colorplot::getLast()->setBlockSize(512);
}
void AudioCaptureManager::dataCallback(float* data, unsigned int frames, bool*done){
*done = !run;
if(!data)
return;
if(channels<0)
return;
int firstIndex = -1;
for (int i = 0; i < channels; ++i) {
if(data[i]!=0){
firstIndex=i;
break;
}
}
if(firstIndex==-1)
return;
sample.addData(data,data+frames*static_cast<unsigned>(channels),channels-1,firstIndex);
audiofft.analyse(sample.data(),1,fftoutput.data());
//db scale
std::transform(fftoutput.begin(),fftoutput.end(),fftoutput.begin(),[](auto i){return 10*std::log10(1+i);});
if(Graph::getLast())
Graph::getLast()->showData(fftoutput.data(),fftoutput.size());
if(Colorplot::getLast()){
Colorplot::getLast()->startBlock();
for (int i = 0; i < 512; ++i) {
Colorplot::getLast()->pushDataToBlock(fftoutput.at(i));
}
Colorplot::getLast()->endBlock();
}
if(Oscillogram::getLast())
Oscillogram::getLast()->showData(sample.data(),sample.size());
}
bool AudioCaptureManager::startCapturing(QString filePathToCaptureLibrary){
typedef int (*capture)(void(*)(int),void(*)(float*,unsigned int, bool*)) ;
auto func = reinterpret_cast<capture>(QLibrary::resolve(filePathToCaptureLibrary,"captureAudio"));
if(func){
captureAudioThread = std::thread([this,func](){
run = true;
func(&AudioCaptureManager::staticInitCallback,&AudioCaptureManager::staticDataCallback);
});
}
return func;
}
}
#ifndef AUDIOCAPTUREMANAGER_H
#define AUDIOCAPTUREMANAGER_H
#include "sample.h"
#include <thread>
#include "audio_fft.h"
namespace Audio {
/**
* @brief The AudioCaptureManager class gets the data from the captureWindowsSountoutput Project and analyse the data and give the data to the other components
*/
class AudioCaptureManager
{
Sample<float,4096> sample;
std::array<float,2048> fftoutput;
std::thread captureAudioThread;
std::atomic_bool run;
AudioFFT audiofft;
int channels = -1;
private:
AudioCaptureManager();
~AudioCaptureManager(){
if(captureAudioThread.joinable()){
run.store(false);
captureAudioThread.join();
}
}
private:
static void staticInitCallback(int channels){get().initCallback(channels);}
static void staticDataCallback(float* data, unsigned int frames, bool*done){get().dataCallback(data,frames,done);}
void initCallback(int channels);
void dataCallback(float* data, unsigned int frames, bool*done);
public:
bool startCapturing(QString filePathToCaptureLibrary);
public:
AudioCaptureManager(AudioCaptureManager const&) = delete;
void operator=(AudioCaptureManager const&) = delete;
static AudioCaptureManager & get(){static AudioCaptureManager m;return m;}
};
}
#endif // AUDIOCAPTUREMANAGER_H
#include "sample.h"
#ifndef SAMPLE_H
#define SAMPLE_H
#include <array>
#include <cstring>
#include <algorithm>
#include <cassert>
#include <QtCore>
namespace Audio {
template<typename Type, std::size_t size_>
class Sample
{
std::array<Type,size_> array;
public:
Sample(){
std::memset(array.data(),0,array.size()*sizeof (Type));
}
/**
* @brief addData adds data to the end of the sample and moves old data to the left
* @param newData a pointer to the new Data
* @param endPointer a pointer pointing to the byte after the data block, like the std::end by the
* @param interleaved space between two relevant data values, eg. 1 by sterio data
* @param startOffset the offset from the newData Pointer to the first relevant byte
*/
void addData(Type * newData, Type * endPointer, int interleaved = 0, int startOffset = 0){
Q_ASSERT(newData<endPointer);
newData += startOffset;
int dis = std::distance(newData,endPointer);
int length = (dis+interleaved) / (1+interleaved);
if(length >= size_){
--endPointer;
for (auto i = array.rbegin();i != array.rend();++i,std::advance(endPointer,-(1+interleaved))) {
*i = *endPointer;
}
return;
}
std::copy(std::next(array.cbegin(),length),array.cend(),array.begin());
for ( auto i = std::next(array.begin(),array.size()-length);newData<endPointer;++i,std::advance(newData,1+interleaved)) {
*i = *newData;
Q_ASSERT(i != array.cend());
}
//Q_ASSERT(newData == endPointer);
}
const std::array<Type,size_> & getArray()const{return array;}
std::array<Type,size_> & getArray(){return array;}
Type* data(){return array.data();}
const Type* data()const{return array.data();}
std::size_t size(){return array.size();}
};
}
#endif // SAMPLE_H
#include "colorplot.h"
#include "QSGFlatColorMaterial"
#include <QSGGeometryNode>
#include <QSGVertexColorMaterial>
Colorplot::Colorplot()
Colorplot::Colorplot():haveNewData(false)
{
setFlag(ItemHasContents);
lastCreated = this;
}
Colorplot * Colorplot::lastCreated = nullptr;
QSGNode * Colorplot::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *){
QSGNode *node = nullptr;
QSGGeometryNode *pointNode = nullptr;
QSGGeometry *pointGeometry = nullptr;
QSGGeometryNode *lineNode = nullptr;
QSGGeometry *lineGeometry = nullptr;
mutex.lock();
int size = dataBlocks.size() * blockSize;
int size2 = dataBlocks.size() * (blockSize+1);
if (!oldNode) {
node = new QSGNode;
/*{
pointNode = new QSGGeometryNode;
pointGeometry = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), size);
pointGeometry->setLineWidth(2);
pointGeometry->setDrawingMode(QSGGeometry::DrawPoints);
pointNode->setGeometry(pointGeometry);
pointNode->setFlag(QSGNode::OwnsGeometry);
pointNode->setMaterial(new QSGVertexColorMaterial);
pointNode->setFlag(QSGNode::OwnsMaterial);
}
node->appendChildNode(pointNode);*/
{
lineNode = new QSGGeometryNode;
lineGeometry = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), size2);
lineGeometry->setLineWidth(1);
lineGeometry->setDrawingMode(QSGGeometry::DrawLineStrip);
lineNode->setGeometry(lineGeometry);
lineNode->setFlag(QSGNode::OwnsGeometry);
lineNode->setMaterial(new QSGVertexColorMaterial);
lineNode->setFlag(QSGNode::OwnsMaterial);
}
node->appendChildNode(lineNode);
} else {
node = static_cast<QSGNode *>(oldNode);
/*pointNode = static_cast<QSGGeometryNode *>(node->childAtIndex(0));
pointGeometry = pointNode->geometry();
pointGeometry->allocate(size);*/
lineNode = static_cast<QSGGeometryNode *>(node->childAtIndex(0));
lineGeometry = lineNode->geometry();
lineGeometry->allocate(size2);
}
//QSGGeometry::ColoredPoint2D *points = pointGeometry->vertexDataAsColoredPoint2D();
QSGGeometry::ColoredPoint2D *lines = lineGeometry->vertexDataAsColoredPoint2D();
int counter = 0;
int x = 0;
for(auto block : dataBlocks){
++x;
lines->x = x + 50;
lines->y = height()-(blockSize-1)*2-1;
++lines;
for (int i = 0; i < blockSize; ++i) {
lines->x = x + 50;
// points->x = x*2;
lines->y /*= points->y*/ = height()-i*2-1;
lines->a /*= points->a*/ = 255;
lines->r /*= points->r*/ = (unsigned char)(block[i]*0.5>255.f?255:block[i]*0.5);
lines->g /*= points->g*/ = (unsigned char)std::min(block[i]*0.2f,255.f);
lines->g /*= points->g*/ = (unsigned char)std::min(block[i]/20*255,255.f);
lines->r /*= points->b*/ = (unsigned char)(block[i]/10 * 255);
++lines; //++points;
++counter;
}
}
//qDebug()<<"counter : " << counter << " size : "<< size << " blocks : "<< dataBlocks.size();
mutex.unlock();
haveNewData = false;
//pointNode->markDirty(QSGNode::DirtyGeometry);
lineNode->markDirty(QSGNode::DirtyGeometry);
return node;
}
......@@ -2,10 +2,78 @@
#define COLORPLOT_H
class Colorplot
#include <QQuickItem>
#include <list>
#include <mutex>
class Colorplot : public QQuickItem
{
Q_OBJECT
unsigned int blockSize = 0;
std::list<volatile float*> dataBlocks;
std::list<float*> freeBlocks;
int currentBlockCounter = -1;
QColor lineColor = QColor(0,0,0);
Q_PROPERTY(QColor lineColor READ getLineColor WRITE setLineColor NOTIFY lineColorChanged)
static Colorplot * lastCreated;
std::atomic_bool haveNewData;
const static unsigned int MAX_BLOCKS_COUNT = 900;
std::mutex mutex;
public:
Colorplot();
~Colorplot(){
if(lastCreated==this)
lastCreated = nullptr;
}
static Colorplot * getLast(){return lastCreated;}
void startBlock(){
mutex.lock();
if (dataBlocks.size()>=MAX_BLOCKS_COUNT) {
currentBlockCounter = 0;
auto data = dataBlocks.front();
dataBlocks.pop_front();
dataBlocks.push_back(data);
}else{
currentBlockCounter = 0;
auto data = new float[blockSize];
memset(data,0,blockSize*sizeof(float));
dataBlocks.push_back(data);
}
}
void endBlock(){
mutex.unlock();
}
void pushDataToBlock(float d){
if (currentBlockCounter>=0) {
dataBlocks.back()[currentBlockCounter] = d;//*0.4f;//std::pow(1+d*0.001,3)*20;
++currentBlockCounter;
if(currentBlockCounter>=blockSize)
currentBlockCounter=-1;
}else
qDebug()<<"Error : currentBlockCounter less then 0";
}
void setBlockSize(unsigned int size){
if(size!=this->blockSize){
for(const auto i : dataBlocks)
delete i;
for(const auto i : freeBlocks)
delete i;
dataBlocks.clear();
freeBlocks.clear();
currentBlockCounter = -1;
blockSize=size;
}
}
void setLineColor(QColor c){lineColor=c;update();lineColorChanged();}
QColor getLineColor(){return lineColor;}
protected:
virtual QSGNode * updatePaintNode(QSGNode *, UpdatePaintNodeData *)override;
signals:
void lineColorChanged();
public slots:
};
#endif // COLORPLOT_H
\ No newline at end of file
#endif // COLORPLOT_H
#include "graph.h"
#include "QSGFlatColorMaterial"
#include <QSGGeometryNode>
#include <cmath>
Graph::Graph()
Graph::Graph():haveNewData(false)
{
setFlag(ItemHasContents);
lastCreated = this;
}
Graph * Graph::lastCreated = nullptr;
float mins = 1;
int counter = 1;
QSGNode * Graph::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *){
QSGNode *node = nullptr;
QSGGeometryNode *lineNode = nullptr;
QSGGeometry *lineGeometry = nullptr;
if (!oldNode) {
node = new QSGNode;
{
lineNode = new QSGGeometryNode;
lineGeometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), size);
lineGeometry->setLineWidth(1);
lineGeometry->setDrawingMode(QSGGeometry::DrawLineStrip);
lineNode->setGeometry(lineGeometry);
lineNode->setFlag(QSGNode::OwnsGeometry);
QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
material->setColor(lineColor);
lineNode->setMaterial(material);
lineNode->setFlag(QSGNode::OwnsMaterial);
}
/*{
pointNode = new QSGGeometryNode;
pointGeometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 4);
pointGeometry->setLineWidth(1);
pointGeometry->setDrawingMode(QSGGeometry::DrawTriangleStrip);
pointNode->setGeometry(pointGeometry);
pointNode->setFlag(QSGNode::OwnsGeometry);
QSGFlatColorMaterial * material = new QSGFlatColorMaterial;
material->setColor(backgroundColor);
pointNode->setMaterial(material);
pointNode->setFlag(QSGNode::OwnsMaterial);
}
node->appendChildNode(pointNode);*/
node->appendChildNode(lineNode);
} else {
node = static_cast<QSGNode *>(oldNode);
lineNode = static_cast<QSGGeometryNode *>(node->childAtIndex(0));
lineGeometry = lineNode->geometry();
lineGeometry->allocate(size);
static_cast<QSGFlatColorMaterial*>(lineNode->material())->setColor(lineColor);
/*pointNode = static_cast<QSGGeometryNode *>(node->childAtIndex(0));
pointGeometry = pointNode->geometry();
pointGeometry->allocate(4);
static_cast<QSGFlatColorMaterial*>(pointNode->material())->setColor(backgroundColor);*/
}
QSGGeometry::Point2D *vertices = lineGeometry->vertexDataAsPoint2D();
/*if(haveNewData.load()){
float min = 999999;
float max = 0;
for(int i = 0 ; i< size; ++i){
data[i] = (std::log10(data[i]));
min = std::min(min,data[i]);
max = std::max(max,data[i]);
}
for(int i = 0 ; i< size; ++i){
data[i]-=min;
data[i]/=(max-min);
data[i] = std::pow(data[i],2);
}
if(min > 0)
mins += min;
++counter;
}
float scale = 0.1;
float curMin = mins/counter;
qDebug() << ' '<<mins << ' ' << curMin <<' '<<counter;
*/
for(int i = 0 ; i< size; ++i){
vertices->x = i*2;
//vertices->y = height() - 50 - 20* (std::log10(data[i]));
vertices->y = height() - 50 - 2*data[i];
++vertices;
}
haveNewData = false;
lineNode->markDirty(QSGNode::DirtyGeometry);
return node;
}
......@@ -6,12 +6,32 @@
class Graph : public QQuickItem
{
Q_OBJECT
float data[2048];
int size = 0;
QColor lineColor = QColor(0,0,0);
Q_PROPERTY(QColor lineColor READ getLineColor WRITE setLineColor NOTIFY lineColorChanged)
static Graph * lastCreated;
std::atomic_bool haveNewData;
public:
Graph();
~Graph(){
if(lastCreated==this)
lastCreated = nullptr;
}
static Graph * getLast(){return lastCreated;}
void showData(float* data, int size){
this->size = std::min(2048,size);
memcpy(this->data,data,this->size*sizeof (float));
haveNewData.store(true);
}
void setLineColor(QColor c){lineColor=c;update();lineColorChanged();}
QColor getLineColor(){return lineColor;}
protected:
virtual QSGNode * updatePaintNode(QSGNode *, UpdatePaintNodeData *)override;
signals:
void lineColorChanged();
public slots:
};
#endif // GRAPH_H
\ No newline at end of file
#endif // GRAPH_H
libAudioFFT.1.0.0.dylib
\ No newline at end of file
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