current version.. forgot to commit
This commit is contained in:
@@ -24,39 +24,27 @@ INCLUDE_DIRECTORIES(
|
|||||||
/usr/include/glib-2.0
|
/usr/include/glib-2.0
|
||||||
/usr/lib64/glib-2.0/include
|
/usr/lib64/glib-2.0/include
|
||||||
/usr/lib/x86_64-linux-gnu/glib-2.0/include
|
/usr/lib/x86_64-linux-gnu/glib-2.0/include
|
||||||
/mnt/vm/workspace/IRGame/
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
FILE(GLOB HEADERS
|
|
||||||
./*.h
|
|
||||||
)
|
|
||||||
|
|
||||||
FILE(GLOB SOURCES
|
|
||||||
./*.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# system specific compiler flags
|
|
||||||
ADD_DEFINITIONS(
|
|
||||||
# -O2
|
|
||||||
-std=c++11
|
|
||||||
-Wall
|
|
||||||
-Werror=return-type
|
|
||||||
-Wextra
|
|
||||||
#-g
|
|
||||||
-O2
|
|
||||||
# #-Wconversion
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# GSTREAMER PLUGIN
|
# GSTREAMER PLUGIN
|
||||||
|
|
||||||
|
FILE(GLOB GST_HEADERS
|
||||||
|
./*.h
|
||||||
|
./lib/*.h
|
||||||
|
./gst/*.h
|
||||||
|
)
|
||||||
|
|
||||||
|
FILE(GLOB GST_SOURCES
|
||||||
|
./*.cpp
|
||||||
|
./lib/*.cpp
|
||||||
|
./gst/*.cpp
|
||||||
|
)
|
||||||
|
|
||||||
ADD_LIBRARY(
|
ADD_LIBRARY(
|
||||||
gst_beat_plugin SHARED
|
gst_beat_plugin SHARED
|
||||||
plugin.cpp
|
${GST_SOURCES}
|
||||||
${HEADERS}
|
${GST_HEADERS}
|
||||||
)
|
)
|
||||||
|
|
||||||
# pkg-config --cflags --libs gstreamer-1.0
|
# pkg-config --cflags --libs gstreamer-1.0
|
||||||
@@ -69,13 +57,46 @@ ADD_DEFINITIONS(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# system specific compiler flags
|
||||||
|
ADD_DEFINITIONS(
|
||||||
|
|
||||||
|
-std=c++11
|
||||||
|
-Wall
|
||||||
|
-Werror=return-type
|
||||||
|
-Wextra
|
||||||
|
#-g
|
||||||
|
-O2
|
||||||
|
# #-Wconversion
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# EXECUTABLE RECORDING FROM PULSEAUDIO
|
# EXECUTABLE RECORDING FROM PULSEAUDIO
|
||||||
|
|
||||||
|
FILE(GLOB PA_HEADERS
|
||||||
|
./*.h
|
||||||
|
./lib/*.h
|
||||||
|
./pa/*.h
|
||||||
|
)
|
||||||
|
|
||||||
|
FILE(GLOB PA_SOURCES
|
||||||
|
./*.cpp
|
||||||
|
./lib/*.cpp
|
||||||
|
./pa/*.cpp
|
||||||
|
)
|
||||||
|
|
||||||
ADD_EXECUTABLE(
|
ADD_EXECUTABLE(
|
||||||
paBeatRecorder
|
paBeatRecorder
|
||||||
main.cpp
|
${PA_HEADERS}
|
||||||
${HEADERS}
|
${PA_SOURCES}
|
||||||
#${SOURCES}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
TARGET_LINK_LIBRARIES(
|
TARGET_LINK_LIBRARIES(
|
||||||
|
|||||||
@@ -7,13 +7,13 @@
|
|||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
|
||||||
|
|
||||||
#include "BeatDetection.h"
|
#include "../lib/BeatDetection.h"
|
||||||
static BeatDetection<float> beatDetection;
|
static BeatDetection<float> beatDetection;
|
||||||
|
|
||||||
#include "BassDetection.h"
|
#include "../lib/BassDetection.h"
|
||||||
static BassDetection<float> bassDetection;
|
static BassDetection<float> bassDetection;
|
||||||
|
|
||||||
#include "BeatDetection2.h"
|
#include "../lib/BeatDetection2.h"
|
||||||
static BeatDetection2<float> beatDetection2;
|
static BeatDetection2<float> beatDetection2;
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_STATIC (beat_detector_debug);
|
GST_DEBUG_CATEGORY_STATIC (beat_detector_debug);
|
||||||
@@ -1,10 +1,14 @@
|
|||||||
#ifndef BASSDETECTION_H
|
#ifndef BASSDETECTION_H
|
||||||
#define BASSDETECTION_H
|
#define BASSDETECTION_H
|
||||||
|
|
||||||
|
//#define PLOT_ME
|
||||||
|
|
||||||
|
#ifdef PLOT_ME
|
||||||
#include <KLib/misc/gnuplot/Gnuplot.h>
|
#include <KLib/misc/gnuplot/Gnuplot.h>
|
||||||
#include <KLib/misc/gnuplot/GnuplotPlot.h>
|
#include <KLib/misc/gnuplot/GnuplotPlot.h>
|
||||||
#include <KLib/misc/gnuplot/GnuplotPlotElementLines.h>
|
#include <KLib/misc/gnuplot/GnuplotPlotElementLines.h>
|
||||||
#include <KLib/misc/gnuplot/GnuplotSplot.h>
|
#include <KLib/misc/gnuplot/GnuplotSplot.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "BiquadFilterGate.h"
|
#include "BiquadFilterGate.h"
|
||||||
#include "MovingAVG.h"
|
#include "MovingAVG.h"
|
||||||
@@ -14,9 +18,11 @@
|
|||||||
|
|
||||||
template <typename Scalar> class BassDetection {
|
template <typename Scalar> class BassDetection {
|
||||||
|
|
||||||
|
#ifdef PLOT_ME
|
||||||
K::Gnuplot gp;
|
K::Gnuplot gp;
|
||||||
K::GnuplotPlot plot;
|
K::GnuplotPlot plot;
|
||||||
K::GnuplotPlotElementLines lines0;
|
K::GnuplotPlotElementLines lines0;
|
||||||
|
#endif
|
||||||
|
|
||||||
BiquadFilterGate<1> filter;
|
BiquadFilterGate<1> filter;
|
||||||
MovingAVG<float> avg;
|
MovingAVG<float> avg;
|
||||||
@@ -27,7 +33,9 @@ public:
|
|||||||
/** setup */
|
/** setup */
|
||||||
BassDetection() : avg(2500), avgLong(100000) {
|
BassDetection() : avg(2500), avgLong(100000) {
|
||||||
setSampleRate(44100);
|
setSampleRate(44100);
|
||||||
|
#ifdef PLOT_ME
|
||||||
plot.add(&lines0);
|
plot.add(&lines0);
|
||||||
|
#endif
|
||||||
avgLong.add(1);
|
avgLong.add(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,11 +65,15 @@ public:
|
|||||||
const float delta = res2 - prev;
|
const float delta = res2 - prev;
|
||||||
prev = res2;
|
prev = res2;
|
||||||
|
|
||||||
|
#ifdef PLOT_ME
|
||||||
lines0.add(K::GnuplotPoint2(x, delta));
|
lines0.add(K::GnuplotPoint2(x, delta));
|
||||||
|
#endif
|
||||||
|
|
||||||
// debug view?
|
// debug view?
|
||||||
//if (x % 6000 == 0) {show();}
|
//if (x % 6000 == 0) {show();}
|
||||||
|
#ifdef PLOT_ME
|
||||||
show();
|
show();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (x % 1000 == 0) {
|
if (x % 1000 == 0) {
|
||||||
return delta;
|
return delta;
|
||||||
@@ -76,6 +88,8 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PLOT_ME
|
||||||
void show() {
|
void show() {
|
||||||
|
|
||||||
int limit = 500;
|
int limit = 500;
|
||||||
@@ -93,6 +107,7 @@ public:
|
|||||||
gp.flush();
|
gp.flush();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1,10 +1,14 @@
|
|||||||
#ifndef ANALYZER_H
|
#ifndef ANALYZER_H
|
||||||
#define ANALYZER_H
|
#define ANALYZER_H
|
||||||
|
|
||||||
|
//#define PLOT_ME
|
||||||
|
|
||||||
|
#ifdef PLOT_ME
|
||||||
#include <KLib/misc/gnuplot/Gnuplot.h>
|
#include <KLib/misc/gnuplot/Gnuplot.h>
|
||||||
#include <KLib/misc/gnuplot/GnuplotPlot.h>
|
#include <KLib/misc/gnuplot/GnuplotPlot.h>
|
||||||
#include <KLib/misc/gnuplot/GnuplotPlotElementLines.h>
|
#include <KLib/misc/gnuplot/GnuplotPlotElementLines.h>
|
||||||
#include <KLib/misc/gnuplot/GnuplotSplot.h>
|
#include <KLib/misc/gnuplot/GnuplotSplot.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "BiquadFilterGate.h"
|
#include "BiquadFilterGate.h"
|
||||||
#include "MovingAVG.h"
|
#include "MovingAVG.h"
|
||||||
@@ -48,9 +52,11 @@ template <typename Scalar> struct BeatBand {
|
|||||||
|
|
||||||
template <typename Scalar> class BeatDetection {
|
template <typename Scalar> class BeatDetection {
|
||||||
|
|
||||||
|
#ifdef PLOT_ME
|
||||||
K::Gnuplot gp;
|
K::Gnuplot gp;
|
||||||
K::GnuplotPlot plot;
|
K::GnuplotPlot plot;
|
||||||
K::GnuplotPlotElementLines lines0;
|
K::GnuplotPlotElementLines lines0;
|
||||||
|
#endif
|
||||||
|
|
||||||
BeatBand<float> band0;
|
BeatBand<float> band0;
|
||||||
BeatBand<float> band1;
|
BeatBand<float> band1;
|
||||||
@@ -67,7 +73,9 @@ public:
|
|||||||
/** setup */
|
/** setup */
|
||||||
BeatDetection() : avg1(600), avg2(10000) {
|
BeatDetection() : avg1(600), avg2(10000) {
|
||||||
setSampleRate(44100);
|
setSampleRate(44100);
|
||||||
|
#ifdef PLOT_ME
|
||||||
plot.add(&lines0);
|
plot.add(&lines0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSampleRate(int srate) {
|
void setSampleRate(int srate) {
|
||||||
@@ -126,14 +134,18 @@ public:
|
|||||||
// area = 0;
|
// area = 0;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
#ifdef PLOT_ME
|
||||||
if (xxx % 8 == 0) {
|
if (xxx % 8 == 0) {
|
||||||
lines0.add(K::GnuplotPoint2(x, yy));
|
lines0.add(K::GnuplotPoint2(x, yy));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// debug view?
|
// debug view?
|
||||||
|
#ifdef PLOT_ME
|
||||||
if (xxx % 5000 == 0) {show();}
|
if (xxx % 5000 == 0) {show();}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (beat) {
|
if (beat) {
|
||||||
std::cout << band0.getMul() << " " << band1.getMul() << " " << band2.getMul() << std::endl;
|
std::cout << band0.getMul() << " " << band1.getMul() << " " << band2.getMul() << std::endl;
|
||||||
@@ -152,6 +164,7 @@ public:
|
|||||||
return beat;
|
return beat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PLOT_ME
|
||||||
void show() {
|
void show() {
|
||||||
|
|
||||||
int limit = 8000;
|
int limit = 8000;
|
||||||
@@ -169,6 +182,7 @@ public:
|
|||||||
gp.flush();
|
gp.flush();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2,10 +2,7 @@
|
|||||||
#define BEATDETECTION2_H
|
#define BEATDETECTION2_H
|
||||||
|
|
||||||
|
|
||||||
#include <KLib/misc/gnuplot/Gnuplot.h>
|
|
||||||
#include <KLib/misc/gnuplot/GnuplotPlot.h>
|
|
||||||
#include <KLib/misc/gnuplot/GnuplotPlotElementLines.h>
|
|
||||||
#include <KLib/misc/gnuplot/GnuplotSplot.h>
|
|
||||||
|
|
||||||
#include "BiquadFilterGate.h"
|
#include "BiquadFilterGate.h"
|
||||||
#include "MovingAVG.h"
|
#include "MovingAVG.h"
|
||||||
@@ -15,6 +12,13 @@
|
|||||||
|
|
||||||
//#define PLOT_ME
|
//#define PLOT_ME
|
||||||
|
|
||||||
|
#ifdef PLOT_ME
|
||||||
|
#include <KLib/misc/gnuplot/Gnuplot.h>
|
||||||
|
#include <KLib/misc/gnuplot/GnuplotPlot.h>
|
||||||
|
#include <KLib/misc/gnuplot/GnuplotPlotElementLines.h>
|
||||||
|
#include <KLib/misc/gnuplot/GnuplotSplot.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define BD2_SHORT 1024
|
#define BD2_SHORT 1024
|
||||||
|
|
||||||
template <typename Scalar> struct BeatBand2 {
|
template <typename Scalar> struct BeatBand2 {
|
||||||
@@ -154,12 +158,12 @@ public:
|
|||||||
|
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
|
|
||||||
const float ratio0 = band0.getRatio();
|
//const float ratio0 = band0.getRatio();
|
||||||
const float var0 = band0.getVariance();
|
//const float var0 = band0.getVariance();
|
||||||
const float stdDev0 = band0.getDiffStdDev();
|
const float stdDev0 = band0.getDiffStdDev();
|
||||||
const float diff0 = band0.avgShort.get() - band0.avgLong.get();
|
//const float diff0 = band0.avgShort.get() - band0.avgLong.get();
|
||||||
const float avgShort0 = band0.avgShort.get();
|
const float avgShort0 = band0.avgShort.get();
|
||||||
const float avgLong0 = band0.avgLong.get();
|
//const float avgLong0 = band0.avgLong.get();
|
||||||
const float threshold0 = band0.avgLong.get() + stdDev0 * thresholdMul; // HERE!
|
const float threshold0 = band0.avgLong.get() + stdDev0 * thresholdMul; // HERE!
|
||||||
|
|
||||||
|
|
||||||
@@ -191,7 +195,7 @@ public:
|
|||||||
if (block > 0 && gapFound) {--block;}
|
if (block > 0 && gapFound) {--block;}
|
||||||
|
|
||||||
if (block == 0 && curIsBeat) {
|
if (block == 0 && curIsBeat) {
|
||||||
block = 6; // very short!
|
block = 8; // very short!
|
||||||
gapFound = false;
|
gapFound = false;
|
||||||
//std::cout << ratio0 << " : " << var0 << " : " << C << std::endl;
|
//std::cout << ratio0 << " : " << var0 << " : " << C << std::endl;
|
||||||
return true;
|
return true;
|
||||||
@@ -10,6 +10,8 @@ using Frequency = float;
|
|||||||
using Amplitude = float;
|
using Amplitude = float;
|
||||||
using SampleRate = int;
|
using SampleRate = int;
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <cmath>
|
||||||
#define K_PI M_PI
|
#define K_PI M_PI
|
||||||
|
|
||||||
/**
|
/**
|
||||||
216
lib/NetworkAddress.h
Normal file
216
lib/NetworkAddress.h
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
#ifndef NETWORKADDRESS_H
|
||||||
|
#define NETWORKADDRESS_H
|
||||||
|
|
||||||
|
#ifndef K_SOCKETS_NETWORKADDRESS_H
|
||||||
|
#define K_SOCKETS_NETWORKADDRESS_H
|
||||||
|
|
||||||
|
#include "../exception.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
|
|
||||||
|
class NetworkAddress {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief create NetworkAddress from the given socket address. This will
|
||||||
|
* mainly be used for incoming data frames. The ctor re-calculuates the
|
||||||
|
* host-ip and port-number from the given address
|
||||||
|
* @param address the socket address to parse
|
||||||
|
*/
|
||||||
|
NetworkAddress(const struct sockaddr_in& address) : port(0), sockAddr(address) {
|
||||||
|
port = ntohs(sockAddr.sin_port);
|
||||||
|
ipFromAddressStruct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief create a new NetworkAddress identified by hostname and port-number
|
||||||
|
* @param host the host to identify (e.g. "127.0.0.1" or "google.de")
|
||||||
|
* @param port the 16-bit port-number to use
|
||||||
|
*/
|
||||||
|
NetworkAddress(const std::string& host, const uint16_t port) : port(port) {
|
||||||
|
|
||||||
|
// convert hostname to ip
|
||||||
|
struct hostent* he = gethostbyname( host.c_str() );
|
||||||
|
if (!he) {throw Exception("error while retrieving IP for hostname: '" + host + "'");}
|
||||||
|
|
||||||
|
// sanity checks
|
||||||
|
// https://www.cs.rutgers.edu/~pxk/417/notes/sockets/udp.html
|
||||||
|
|
||||||
|
// build address struct
|
||||||
|
memset( &sockAddr, 0, sizeof(sockAddr) );
|
||||||
|
sockAddr.sin_family = AF_INET;
|
||||||
|
//sockAddr.sin_addr = *((struct in_addr*)he->h_addr);
|
||||||
|
sockAddr.sin_port = htons(port);
|
||||||
|
memcpy((void*)&sockAddr.sin_addr, he->h_addr_list[0], he->h_length);
|
||||||
|
|
||||||
|
ipFromAddressStruct();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief create a new NetworkAddress identified by the given port-number and ANY host-name
|
||||||
|
* @param port the 16-bit port-number to use
|
||||||
|
*/
|
||||||
|
NetworkAddress(const uint16_t port) : port(port) {
|
||||||
|
|
||||||
|
// build address struct
|
||||||
|
memset( &sockAddr, 0, sizeof(sockAddr) );
|
||||||
|
sockAddr.sin_family = AF_INET;
|
||||||
|
sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
sockAddr.sin_port = htons(port);
|
||||||
|
|
||||||
|
ipFromAddressStruct();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief create a new NetworkAddress matching ANY host and ANY port
|
||||||
|
* e.g. used for receiving all UDP-datagrams sent to any local port / interface
|
||||||
|
*/
|
||||||
|
NetworkAddress() : port(0) {
|
||||||
|
|
||||||
|
// build address struct
|
||||||
|
memset( &sockAddr, 0, sizeof(sockAddr) );
|
||||||
|
sockAddr.sin_family = AF_INET;
|
||||||
|
sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
sockAddr.sin_port = htons(0);
|
||||||
|
|
||||||
|
ipFromAddressStruct();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** copy ctor */
|
||||||
|
NetworkAddress(const NetworkAddress& other) :
|
||||||
|
port(other.port), sockAddr(other.sockAddr) {
|
||||||
|
|
||||||
|
ipFromAddressStruct();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** get a NetworkAddress to broadcast to the given port */
|
||||||
|
static NetworkAddress getForBroadcast(const uint16_t port) {
|
||||||
|
NetworkAddress adr;
|
||||||
|
memset(&adr.sockAddr, 0, sizeof(adr.sockAddr));
|
||||||
|
adr.sockAddr.sin_family = AF_INET;
|
||||||
|
adr.sockAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
|
||||||
|
adr.sockAddr.sin_port = htons(port);
|
||||||
|
adr.port = port;
|
||||||
|
return adr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// /** assignment operator */
|
||||||
|
// void operator = (const NetworkAddress& other) {
|
||||||
|
// this->hostName = other.hostName;
|
||||||
|
// this->hostIP = other.hostIP;
|
||||||
|
// this->port = other.port;
|
||||||
|
// this->sockAddr = other.sockAddr;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
/** dtor */
|
||||||
|
~NetworkAddress() {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** get the network address as sockaddr_in struct */
|
||||||
|
const struct sockaddr_in& getAsSocketAddress() const {
|
||||||
|
return sockAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// /** get the remote's port */
|
||||||
|
// uint16_t getPort() const {
|
||||||
|
// return port;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /** get the host's IP as string */
|
||||||
|
// const std::string& getHostIP() const {
|
||||||
|
// return hostIP;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /** get the host's name as string */
|
||||||
|
// const std::string& getHostName() {
|
||||||
|
// if (hostName.empty()) { hostNameFromAddressStruct(); }
|
||||||
|
// return hostName;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** is the internal port valid for an outbound packet? */
|
||||||
|
bool isValidTargetPort() const {
|
||||||
|
return port != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** is the internal ip valid for an outbound packet? */
|
||||||
|
bool isValidTargetHost() const {
|
||||||
|
return sockAddr.sin_addr.s_addr != htonl(INADDR_ANY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// /** check whether both NetworkAddresses are equal */
|
||||||
|
// bool operator == (const NetworkAddress& other) const {
|
||||||
|
// return memcmp( &this->sockAddr, &other.sockAddr, sizeof(sockAddr)) == 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/** fill the hostIP string from the address struct */
|
||||||
|
void ipFromAddressStruct() {
|
||||||
|
|
||||||
|
uint32_t ip = sockAddr.sin_addr.s_addr;
|
||||||
|
hostIP = std::to_string( (ip>> 0) & 0xFF ) + "." +
|
||||||
|
std::to_string( (ip>> 8) & 0xFF ) + "." +
|
||||||
|
std::to_string( (ip>>16) & 0xFF ) + "." +
|
||||||
|
std::to_string( (ip>>24) & 0xFF );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// /** fill the hostName string via reverse-lookup of the address struct */
|
||||||
|
// void hostNameFromAddressStruct() {
|
||||||
|
|
||||||
|
// char hostNameBuf[128];
|
||||||
|
// const int flags = 0;
|
||||||
|
|
||||||
|
// // reverse lookup
|
||||||
|
// getnameinfo( (struct sockaddr*) &sockAddr, sizeof(sockAddr), hostNameBuf, 128, nullptr, 0, flags );
|
||||||
|
// this->hostName = std::string(hostNameBuf);
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/** the host's ip as string */
|
||||||
|
std::string hostIP;
|
||||||
|
|
||||||
|
/** the host's name as string */
|
||||||
|
std::string hostName;
|
||||||
|
|
||||||
|
/** the port-number from the ctor */
|
||||||
|
uint16_t port;
|
||||||
|
|
||||||
|
/** the resulting socket-address-struct */
|
||||||
|
struct sockaddr_in sockAddr;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // K_SOCKETS_NETWORKADDRESS_H
|
||||||
|
|
||||||
|
|
||||||
|
#endif // NETWORKADDRESS_H
|
||||||
199
lib/Socket.h
Normal file
199
lib/Socket.h
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
#ifndef SOCKET_H
|
||||||
|
#define SOCKET_H
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#include "NetworkAddress.h"
|
||||||
|
#include "../exception.h"
|
||||||
|
|
||||||
|
class SocketUDP {
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static constexpr int MAX_DATAGRAM_SIZE = 64*1024;
|
||||||
|
|
||||||
|
bool bound = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** ctor */
|
||||||
|
SocketUDP() : handle(0) {
|
||||||
|
|
||||||
|
// create socket
|
||||||
|
handle = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (handle == -1) {throw Exception("error while creating socket");}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** dtor */
|
||||||
|
~SocketUDP() {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief bind the socket to receive all datagrams sent to the given (local) port
|
||||||
|
* a localPort of 0 will let the OS determine a free one.
|
||||||
|
* @param localPort the local endpoint for datagrams sent from a remote
|
||||||
|
*/
|
||||||
|
void bind(const uint16_t localPort) {
|
||||||
|
|
||||||
|
if (bound) {throw Exception("socket already bound!");}
|
||||||
|
|
||||||
|
// local endpoint AF_INET struct
|
||||||
|
struct sockaddr_in srvAddr;
|
||||||
|
memset((char*)&srvAddr, 0, sizeof(srvAddr));
|
||||||
|
srvAddr.sin_family = AF_INET;
|
||||||
|
srvAddr.sin_addr.s_addr = htonl(INADDR_ANY); // every interface
|
||||||
|
srvAddr.sin_port = htons(localPort);
|
||||||
|
|
||||||
|
// bind the socket to the given port
|
||||||
|
int ret = ::bind(handle, (struct sockaddr*) &srvAddr, sizeof(srvAddr));
|
||||||
|
if (ret < 0) {throw Exception("error while binding socket");}
|
||||||
|
|
||||||
|
// mark as bound
|
||||||
|
bound = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** close the socket */
|
||||||
|
void close() {
|
||||||
|
|
||||||
|
// cleanup
|
||||||
|
if (handle) {
|
||||||
|
::close(handle);
|
||||||
|
handle = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// /** is the socket currently closed? */
|
||||||
|
// bool isClosed() const {
|
||||||
|
// return handle == 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /** allow to broadcast packets using this socket? */
|
||||||
|
// void allowBroadcast(const bool allow) {
|
||||||
|
|
||||||
|
// #if defined(__GNUC__)
|
||||||
|
// const int broadcastEnable = (allow) ? (1) : (0);
|
||||||
|
// const int ret = setsockopt(handle, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable));
|
||||||
|
// if (ret < 0) { throw SocketException("error while enabling broadcast", errno); }
|
||||||
|
// #elif defined(_WIN32)
|
||||||
|
// ;
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief send a datagram to the given destination address
|
||||||
|
* @param data the data to send
|
||||||
|
* @param len the length of the data to send (max 64k!)
|
||||||
|
* @param addr the destination address
|
||||||
|
*/
|
||||||
|
void sendDatagram(const uint8_t* data, uint32_t len, const NetworkAddress& addr) {
|
||||||
|
|
||||||
|
// sanity check
|
||||||
|
if (!bound) {throw Exception("bind() the socket first!");}
|
||||||
|
|
||||||
|
// ensure max datagram size
|
||||||
|
if (len > MAX_DATAGRAM_SIZE) {throw Exception("max datagram size is " + std::to_string(MAX_DATAGRAM_SIZE)+ " bytes!");}
|
||||||
|
|
||||||
|
// ensure correct destination address
|
||||||
|
if (!addr.isValidTargetPort()) {throw Exception("the given destination address has no valid port number");}
|
||||||
|
if (!addr.isValidTargetHost()) {throw Exception("the given destination address has no valid hostname");}
|
||||||
|
|
||||||
|
// send datagram to the given destionation
|
||||||
|
const struct sockaddr_in& sockAddr = addr.getAsSocketAddress();
|
||||||
|
const int options = 0;
|
||||||
|
const int res = sendto(handle, (const char*)data, len, options, (struct sockaddr*) &sockAddr, sizeof(sockaddr));
|
||||||
|
|
||||||
|
// check
|
||||||
|
if (res < 0) {throw Exception("error while sending datagram");}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief send a datagram to the given destination address
|
||||||
|
* @param data the data to send (max 64k!)
|
||||||
|
* @param addr the destination address
|
||||||
|
*/
|
||||||
|
void sendDatagram(const std::vector<uint8_t>& data, const NetworkAddress& addr) {
|
||||||
|
sendDatagram(data.data(), (uint32_t) data.size(), addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendDatagram(const std::string& data, const NetworkAddress& addr) {
|
||||||
|
sendDatagram((const uint8_t*)data.data(), data.length(), addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * @brief send the given datagram to its internal destination address
|
||||||
|
// * @param d the datagram to send
|
||||||
|
// */
|
||||||
|
// void sendDatagram(const Datagram& d) {
|
||||||
|
// sendDatagram(d.getData(), d.getLength(), d.getAddress());
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * @brief convenience function for receiveDatagram(d) which returns a new
|
||||||
|
// * datagram instead of reusing an existing one.
|
||||||
|
// * @return a newly created datagram holding the received message
|
||||||
|
// */
|
||||||
|
// DefaultDatagram receiveDatagram() {
|
||||||
|
// DefaultDatagram dd;
|
||||||
|
// receiveDatagram(dd);
|
||||||
|
// return dd;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * @brief this method will block until a new datagram is received on the bound
|
||||||
|
// * port of the underlying socket. the received data will be stored within the
|
||||||
|
// * given datagram
|
||||||
|
// * @param d the buffer to store the received datagram to
|
||||||
|
// */
|
||||||
|
// void receiveDatagram(Datagram& d) {
|
||||||
|
|
||||||
|
// const int flags = 0;
|
||||||
|
// const int maxSize = MAX_DATAGRAM_SIZE;
|
||||||
|
|
||||||
|
// // sanity check
|
||||||
|
// if (!bound) {throw SocketException("bind() the socket first!");}
|
||||||
|
|
||||||
|
// // ensure the target buffer may hold the largest possible datagram
|
||||||
|
// d.ensureSpace(maxSize);
|
||||||
|
|
||||||
|
// // the datagrams sender will be stored here
|
||||||
|
// struct sockaddr_in senderAddr;
|
||||||
|
// socklen_t senderLength = sizeof(senderAddr);
|
||||||
|
|
||||||
|
// // receive datagram from socket and store sender information
|
||||||
|
// int len = recvfrom(handle, (char*) d.getDataWriteable(), maxSize, flags, (struct sockaddr*) &senderAddr, &senderLength);
|
||||||
|
// if (len < 0) {throw SocketException("error while receiving datagram", errno);}
|
||||||
|
|
||||||
|
// // store senders network-address in the datagram
|
||||||
|
// NetworkAddress na(senderAddr);
|
||||||
|
// d.setAddress(na);
|
||||||
|
|
||||||
|
// // inform buffer about the actual size of the datagram
|
||||||
|
// d.setLength( (uint32_t) len );
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/** the socket handle */
|
||||||
|
int handle;
|
||||||
|
|
||||||
|
/** the local address the socket is bound to */
|
||||||
|
NetworkAddress localAddress;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SOCKET_H
|
||||||
35
main.cpp
35
main.cpp
@@ -1,35 +0,0 @@
|
|||||||
#include "pulseaudio.h"
|
|
||||||
|
|
||||||
#include "BeatDetection2.h"
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
|
|
||||||
PulseAudio pa;
|
|
||||||
//pa.join();
|
|
||||||
|
|
||||||
int16_t buf[1024];
|
|
||||||
|
|
||||||
BeatDetection2<float> bestBass(Mode::BASS);
|
|
||||||
BeatDetection2<float> beatSnare(Mode::SNARE);
|
|
||||||
|
|
||||||
while(true) {
|
|
||||||
|
|
||||||
pa.read(buf, 1024);
|
|
||||||
|
|
||||||
for (int i = 0; i < 1024; ++i) {
|
|
||||||
const float left = buf[i];
|
|
||||||
const float right = buf[i];
|
|
||||||
|
|
||||||
const bool bBass = bestBass.add(left, right);
|
|
||||||
if (bBass) {std::cout << "bass\n" << std::flush;}
|
|
||||||
|
|
||||||
const bool bSnare = beatSnare.add(left, right);
|
|
||||||
if (bSnare) {std::cout << "snare...\n" << std::flush;}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
62
pa/main.cpp
Executable file
62
pa/main.cpp
Executable file
@@ -0,0 +1,62 @@
|
|||||||
|
#include "pulseaudio.h"
|
||||||
|
|
||||||
|
#include "../lib/BeatDetection2.h"
|
||||||
|
|
||||||
|
#include "../lib/Socket.h"
|
||||||
|
SocketUDP sck;
|
||||||
|
|
||||||
|
void sendUDP(const std::string& msg) {
|
||||||
|
NetworkAddress destination("127.0.0.1", 5050);
|
||||||
|
sck.sendDatagram(msg, destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
sck.bind(5051);
|
||||||
|
sendUDP("starting");
|
||||||
|
|
||||||
|
// sanity check
|
||||||
|
if (argc != 2) {
|
||||||
|
std::cout << "usage: paBeatRecorder [pa_deviceName]" << std::endl;
|
||||||
|
std::cout << "e.g. paBeatRecorder alsa_output.pci-0000_00_1b.0.analog-stereo.monitor" << std::endl;
|
||||||
|
std::cout << "list devices with: pactl list | grep '\\.monitor'" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the to-be-used device name
|
||||||
|
std::string devName = argv[1];
|
||||||
|
|
||||||
|
PulseAudio pa(devName);
|
||||||
|
//pa.join();
|
||||||
|
|
||||||
|
int16_t buf[1024];
|
||||||
|
|
||||||
|
BeatDetection2<float> bestBass(Mode::BASS);
|
||||||
|
BeatDetection2<float> beatSnare(Mode::SNARE);
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
|
||||||
|
pa.read(buf, 1024);
|
||||||
|
|
||||||
|
for (int i = 0; i < 1024; ++i) {
|
||||||
|
const float left = buf[i];
|
||||||
|
const float right = buf[i];
|
||||||
|
|
||||||
|
const bool bBass = bestBass.add(left, right);
|
||||||
|
if (bBass) {
|
||||||
|
std::cout << "bass\n" << std::flush;
|
||||||
|
sendUDP("bass");
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool bSnare = beatSnare.add(left, right);
|
||||||
|
if (bSnare) {
|
||||||
|
std::cout << "snare...\n" << std::flush;
|
||||||
|
sendUDP("snare");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <pulse/pulseaudio.h>
|
#include <pulse/pulseaudio.h>
|
||||||
#include <pulse/simple.h>
|
#include <pulse/simple.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "exception.h"
|
#include "../exception.h"
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,7 +21,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/** ctor */
|
/** ctor */
|
||||||
PulseAudio() {
|
PulseAudio(const std::string& devName) {
|
||||||
|
|
||||||
sampleSpec.format = PA_SAMPLE_S16LE;
|
sampleSpec.format = PA_SAMPLE_S16LE;
|
||||||
sampleSpec.rate = 44100;
|
sampleSpec.rate = 44100;
|
||||||
@@ -32,7 +32,7 @@ public:
|
|||||||
const char* server = nullptr;
|
const char* server = nullptr;
|
||||||
const char* clientName = "beat detection";
|
const char* clientName = "beat detection";
|
||||||
const char* streamName = "recording beats";
|
const char* streamName = "recording beats";
|
||||||
const char* dev = "alsa_output.pci-0000_00_1b.0.analog-stereo.monitor"; //nullptr;
|
const char* dev = devName.c_str(); //nullptr;
|
||||||
//const char* dev = "alsa_output.usb-0d8c_USB_Sound_Device-00-Device.analog-surround-51.monitor";
|
//const char* dev = "alsa_output.usb-0d8c_USB_Sound_Device-00-Device.analog-surround-51.monitor";
|
||||||
|
|
||||||
// connect
|
// connect
|
||||||
Reference in New Issue
Block a user