Commit 292ebeab authored by Dan Wilcox's avatar Dan Wilcox
Browse files

renamed several source files, formatting cleanups, wave file writer updates

parent 26508615
......@@ -15,21 +15,25 @@
#pragma once
#include "ofxTensorFlow2.h"
#include <queue>
#include <deque>
#include <iostream>
#include "wav_file_writer_beta.h"
#include "ofxTensorFlow2.h"
#include "ofFileUtils.h"
// uncomment to write recorded audio samples to bin/data/test.wav
//#define DEBUG_WAVE
#ifdef DEBUG_WAVE
#include "WavFileWriterBeta.h"
#endif
// a simple Fifo with adjustable max length
template <typename T, typename Container=std::deque<T>>
class FixedFifo : public std::queue<T, Container> {
public:
FixedFifo(const std::size_t maxLength=10) : maxLen(maxLength) {}
void push(const T& value) {
......@@ -44,6 +48,7 @@ class FixedFifo : public std::queue<T, Container> {
}
private:
std::size_t maxLen;
};
......@@ -62,19 +67,17 @@ class AudioClassifier : public ofxTF2::Model {
// downsample and empty the incoming Fifo
downsample(bufferFifo, sample, downsamplingFactor);
normalize(sample);
#if 1
std::string file_name(ofToDataPath("test.wav"));
sakado::WavFileWriterBeta wfw(file_name, 16000, 2, sample.size());
#ifdef DEBUG_WAVE
sakado::WavFileWriterBeta wfw(ofToDataPath("test.wav"), 1, 16000, 2, sample.size());
int16_t buf;
for (int i = 0; i < sample.size(); i++) {
buf = sample[i] *255*100; // scale data to int16 range
wfw.Write(&buf, 2, 1);
for(int i = 0; i < sample.size(); i++) {
buf = sample[i] * 25500; // scale data to int16 range
wfw.write(&buf, 2, 1);
}
wfw.Close();
#endif
wfw.close();
#endif
// convert recorded sample to a batch of size one
ofxTF2::shapeVector tensorShape {1, static_cast<ofxTF2::shape_t>(sample.size()), 1};
......@@ -99,19 +102,19 @@ class AudioClassifier : public ofxTF2::Model {
void normalize(SimpleAudioBuffer & sample) {
// find absolute maximum value
float max = 0.0;
for (const auto& s : sample) {
if (abs(s) > max) {
for(const auto& s : sample) {
if(abs(s) > max) {
max = abs(s);
}
}
if (max == 0.0)
if(max == 0.0) {
return;
for (auto&& s : sample) {
}
for(auto&& s : sample) {
s /= max;
}
}
// downsample by an integer
void downsample(AudioBufferFifo & bufferFifo, SimpleAudioBuffer & sample,
const std::size_t downsamplingFactor) {
......
// adapted from https://github.com/KojiroSakado/WavFileWriterBeta
// Kojiro Sakado 2019
// ref: http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html
#pragma once
#ifdef _MSC_VER
#pragma warning(disable:4996)
#endif
#include <cstdio>
#include <string>
namespace sakado {
/// very basic wave file writer using c stdio
class WavFileWriterBeta {
public:
std::string filename;
/// open file for a fixed-length number of samples
WavFileWriterBeta(std::string filename, unsigned short numChannels,
unsigned long sampleRate,
unsigned short bytesPerSample,
unsigned long numSamples) :
filename(filename) {
char riff[] = "RIFF";
char wave[] = "WAVE";
char fmt[] = "fmt ";
char data[] = "data";
unsigned long numData = numChannels * bytesPerSample * numSamples;
unsigned long bufl;
unsigned long bufs;
fp = fopen(filename.c_str(), "wb");
// header chunk, 12 bytes
fwrite(riff, 1, 4, fp);
bufl = 36 + (numData); // chunk data len
fwrite(&bufl, 1, 4, fp);
fwrite(wave, 1, 4, fp);
// (basic) format chunk, 24 bytes
fwrite(fmt, 1, 4, fp);
bufl = 16; // chunk data len
fwrite(&bufl, 1, 4, fp);
bufs = 1; // format tag
fwrite(&bufs, 1, 2, fp);
bufs = numChannels; // number of channels
fwrite(&bufs, 1, 2, fp);
bufl = sampleRate; // sample rate
fwrite(&bufl, 1, 4, fp);
bufl = bytesPerSample * sampleRate; // average bytes per second
fwrite(&bufl, 1, 4, fp);
bufs = bytesPerSample; // bytes per frame
fwrite(&bufs, 1, 2, fp);
bufs = bytesPerSample * 8; // bits per sample
fwrite(&bufs, 1, 2, fp);
// data chunk
fwrite(data, 1, 4, fp);
bufl = numData * bytesPerSample; // chunk data length
fwrite(&bufl, 1, 4, fp);
}
~WavFileWriterBeta() {
close();
}
/// write nitems of size bytes from buf to file
/// returns number of items written
size_t write(const void *buf, size_t size, size_t nitems) {
return fwrite(buf, size, nitems, fp);
}
/// close file
void close() {
if(fp) {
fclose(fp);
fp = NULL;
}
}
/// reopen file to append, not yet tested
void reopen() {
if(!fp) {
fp = fopen(filename.c_str(), "ab");
}
}
private:
FILE *fp = NULL;
};
} // namespace
......@@ -24,8 +24,9 @@ void ofApp::setup() {
ofBackground(54, 54, 54);
// load the model, bail out on error
//if(!model.load("model_4lang")) {
if(!model.load("model_attrnn")) {
//std::string modelName = "model_4lang"; // model v1
std::string modelName = "model_attrnn"; // model v2
if(!model.load(modelName)) {
std::exit(EXIT_FAILURE);
}
......@@ -38,7 +39,7 @@ void ofApp::setup() {
// downsampling is required for microphones that do not have 16kHz sampling
downsamplingFactor = 3;
inputSeconds = 5;
inputSamplingRate = 16000; // shall not be changed AI was trained on 16kHz
inputSamplingRate = 16000; // shall not be changed, AI was trained on 16kHz
// recording settings
numPreviousBuffers = 10; // how many buffers to save before trigger happens
......@@ -63,13 +64,13 @@ void ofApp::setup() {
settings.bufferSize = bufferSize;
soundStream.setup(settings);
// print words we know
ofLog() << "From src/labels.h:";
ofLog() << "----> words to spot";
// print language labels we know
ofLog() << "From src/Labels.h:";
ofLog() << "----> detected languages";
for(const auto & label : labelsMap) {
ofLog() << label.second;
}
ofLog() << "<---- words to spot";
ofLog() << "<---- detected languages";
// warm up: inital inference involves initalization (takes longer)
auto test = cppflow::fill({1, 80000, 1}, 1.0f);
......
/*
* * Language Identifier
* Language Identifier
*
* Copyright (c) 2021 ZKM | Hertz-Lab
* Paul Bethge <bethge@zkm.de>
......@@ -18,10 +18,9 @@
#include "ofMain.h"
#include "ofxTensorFlow2.h"
#include "ofxOsc.h"
#include "labels.h"
// AudioBufferFifo & AudioClassifier model defined in utils.h
#include "utils.h"
#include "AudioClassifier.h"
#include "Labels.h"
class ofApp : public ofBaseApp {
......
#ifdef SAKADO_WAV_FILE_WRITER_BETA_H
#else
#define SAKADO_WAV_FILE_WRITER_BETA_H
#ifdef _MSC_VER
#pragma warning(disable:4996)
#endif
#include<cstdio>
#include<string>
using namespace::std;
namespace sakado {
class WavFileWriterBeta {
FILE*fp;
public:
unsigned long FmtSize;
unsigned short FmtID;
unsigned short NumChannels;
unsigned long SampleRate;
unsigned long BytesPerSec;
unsigned short BlockAlign;//(bytes per sample)*(channels)
unsigned short BitsPerSample;
unsigned long DataSize;
unsigned short BytesPerSample;
unsigned long NumData;
string Filename;
WavFileWriterBeta(string filename, unsigned long SampleRate, unsigned short BytesPerSample, unsigned long NumData) {
char riff[] = "RIFF";
char wave[] = "WAVE";
char fmt[] = "fmt ";
char data[] = "data";
unsigned long bufl;
unsigned long bufs;
this->Filename = filename;
fp = fopen(filename.c_str(), "wb");
fwrite(riff, 1, 4, fp);
bufl = 36 + (NumData * BytesPerSample);
fwrite(&bufl, 1, 4, fp);
fwrite(wave, 1, 4, fp);
fwrite(fmt, 1, 4, fp);
bufl = 16;
fwrite(&bufl, 1, 4, fp);
bufs = 1;
fwrite(&bufs, 1, 2, fp);
fwrite(&bufs, 1, 2, fp);
bufl = SampleRate;
fwrite(&bufl, 1, 4, fp);
bufl = BytesPerSample * SampleRate;
fwrite(&bufl, 1, 4, fp);
bufs = BytesPerSample;
fwrite(&bufs, 1, 2, fp);
bufs = BytesPerSample * 8;
fwrite(&bufs, 1, 2, fp);
fwrite(data, 1, 4, fp);
bufl = NumData * BytesPerSample;
fwrite(&bufl, 1, 4, fp);
}
~WavFileWriterBeta() {
if(fp != NULL)fclose(fp);
}
unsigned int Write(const void* buf, size_t elementSize, size_t elementCount) {
return fwrite(buf, elementSize, elementCount, fp);
}
void Close() {
if(fp != NULL)fclose(fp);
fp = NULL;
}
//Not yet tested
void Reopen() {
if(fp == NULL)fp = fopen(Filename.c_str(), "ab");
}
};
}
#endif
\ 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