-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Acoustic event detector #46
base: master
Are you sure you want to change the base?
Changes from all commits
2ff0dfe
bbac57a
f16db9f
a9a1e76
ed2315e
df0b123
972b5c2
8bfec1e
a6bba78
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# makefile for user application | ||
|
||
# the current directory | ||
APP_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) | ||
|
||
# files needed for this code | ||
C_SRCS := $(wildcard *.c) | ||
C_SRCS := $(wildcard **/log2fix.c) | ||
#C_SRCS += ./log2fix/log2fix.c | ||
#C_SRCS += ./kiss_fft/kiss_fft.c | ||
#C_SRCS += ./kiss_fft/tools/kiss_fftr.c | ||
#C_SRCS += ./gcwa/c/ridgeTracker.c | ||
#C_SRCS += ./gcwa/c/dynArray.c | ||
|
||
INCLUDE_PATHS += . ./kiss_fft ./kiss_fft/tools ./log2fix ./gcwa/c | ||
|
||
CFLAGS += -DFIXED_POINT=16 -std=c99 | ||
CFLAGS += -Wno-type-limits -Wno-sign-compare | ||
|
||
TOCK_BOARD = audio_module | ||
|
||
# include makefile settings that are shared between applications | ||
include ../../AppMakefile.mk | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Universal acoustic event detection app | ||
The first step into any audio processing chain. | ||
|
||
Detect a large class of "acoustic events" (bird calls, gunshots, broken glasses, etc.) from noisy background. | ||
Further classifications are reserved for downstream processing. | ||
|
||
## Quick start | ||
1. Plug the Audio Module into the `Module 1` slot | ||
|
||
2. **Important** Make sure the programming knob is turned to `MOD1`. | ||
|
||
3. Get all the prerequisites (See below) | ||
|
||
4. Flash the app | ||
|
||
```bash | ||
cd signpost/software/apps/audio_module/event_detector | ||
make flash | ||
``` | ||
|
||
## Prerequisites | ||
* Fixed-point FFT: git clone https://github.com/longle2718/kiss_fft | ||
* Fixed-point log: git clone https://github.com/dmoulding/log2fix | ||
* Ridge tracker: git clone https://bitbucket.org/longle1/gcwa | ||
* Fixed-point implementation in C is under gcwa/c/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
|
||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <unistd.h> | ||
#include <stdint.h> | ||
#include <stdbool.h> | ||
|
||
#include <adc.h> | ||
#include <console.h> | ||
#include <gpio.h> | ||
#include <led.h> | ||
#include <timer.h> | ||
#include <tock.h> | ||
|
||
#include "app_watchdog.h" | ||
#include "signpost_api.h" | ||
#include "simple_post.h" | ||
#include "_kiss_fft_guts.h" | ||
#include "kiss_fftr.h" | ||
#include "common.h" | ||
#include "ridgeTracker.h" | ||
|
||
static int freqAnalyze(kiss_fft_scalar *frame, kiss_fft_scalar *spec); | ||
static int printMat(char *filename, kiss_fft_scalar *in, size_t N); | ||
static int printMat2(char *filename, size_t *in, size_t N); | ||
|
||
int main (void) { | ||
int err = SUCCESS; | ||
printf("[Audio Module] Event Detector\n"); | ||
|
||
// initialize ADC | ||
err = adc_initialize(); | ||
if (err < SUCCESS) { | ||
printf("Initialize errored: %d\n", err); | ||
} | ||
|
||
static kiss_fft_scalar frame[BUF_LEN]; | ||
static kiss_fft_scalar spec[FRE_LEN]; | ||
static kiss_fft_scalar snrOut[FRE_LEN]; | ||
memset(frame, 0, BUF_LEN*sizeof(kiss_fft_scalar)); | ||
size_t frameIdx = 0; | ||
size_t globTI = 0; | ||
ridgeTracker_init(); | ||
while (true) { | ||
// read data from ADC | ||
for (size_t k = frameIdx; k < frameIdx+INC_LEN; k++){ | ||
err = adc_read_single_sample(3); | ||
if (err < SUCCESS) { | ||
printf("ADC read error: %d\n", err); | ||
} | ||
uint16_t sample = err & 0xFFFF; | ||
frame[k] = (kiss_fft_scalar)sample; | ||
} | ||
frameIdx = (frameIdx+INC_LEN) % BUF_LEN; | ||
|
||
// perform FFT | ||
if (freqAnalyze(frame, spec)){ | ||
printf("freqAnalyze() failed!\n"); | ||
return 1; | ||
} | ||
|
||
// ridgetracker update | ||
ridgeTracker_update(spec, snrOut); | ||
|
||
// check for available event | ||
if (ridgeTracker_isReady){ | ||
printf("Event detected!\n"); | ||
printf("ridgeTracker_out.used = %zu\n",ridgeTracker_out.used); | ||
|
||
if (printMat("SNR.mat",ridgeTracker_out.SNR,ridgeTracker_out.used)){ | ||
printf("printMat() failed!\n"); | ||
return 1; | ||
} | ||
if (printMat2("FI.mat",ridgeTracker_out.FI,ridgeTracker_out.used)){ | ||
printf("printMat2() failed!\n"); | ||
return 1; | ||
} | ||
size_t TIE = ridgeTracker_out.TI[ridgeTracker_out.used-1]; | ||
for (size_t k=0; k<ridgeTracker_out.used; k++){ | ||
ridgeTracker_out.TI[k] = globTI-(TIE-ridgeTracker_out.TI[k]); | ||
} | ||
if (printMat2("TI.mat",ridgeTracker_out.TI,ridgeTracker_out.used)){ | ||
printf("printMat2() failed!\n"); | ||
return 1; | ||
} | ||
|
||
ridgeTracker_reset(); | ||
} | ||
globTI += 1; | ||
} | ||
|
||
ridgeTracker_destroy(); | ||
|
||
printf("Done!\n"); | ||
fflush(stdout); | ||
return 0; | ||
} | ||
|
||
static int freqAnalyze(kiss_fft_scalar *frame, kiss_fft_scalar *spec){ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In general, these static helper methods are returning positive integers on error, which is pretty unintuitive for C. I think it would be better to return negative numbers (common for errors) and check There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great, thank you very much for telling me about the correct style in C. I'll fix this accordingly. |
||
// FFT data structure | ||
kiss_fftr_cfg cfg; | ||
kiss_fft_scalar in[BUF_LEN]; | ||
kiss_fft_cpx out[FRE_LEN + 1]; | ||
|
||
static kiss_fft_scalar win[BUF_LEN] = {0x0000,0x0001,0x0004,0x000b,0x0013,0x001e,0x002c,0x003c,0x004f,0x0064,0x007b,0x0095,0x00b2,0x00d0,0x00f2,0x0115,0x013c,0x0164,0x018f,0x01bd,0x01ec,0x021f,0x0253,0x028a,0x02c4,0x0300,0x033e,0x037e,0x03c1,0x0406,0x044e,0x0497,0x04e3,0x0532,0x0583,0x05d5,0x062b,0x0682,0x06dc,0x0737,0x0796,0x07f6,0x0858,0x08bd,0x0923,0x098c,0x09f7,0x0a64,0x0ad3,0x0b44,0x0bb8,0x0c2d,0x0ca4,0x0d1d,0x0d98,0x0e15,0x0e94,0x0f15,0x0f98,0x101d,0x10a4,0x112c,0x11b6,0x1242,0x12d0,0x1360,0x13f1,0x1484,0x1519,0x15af,0x1647,0x16e0,0x177c,0x1818,0x18b7,0x1956,0x19f8,0x1a9a,0x1b3f,0x1be4,0x1c8b,0x1d34,0x1ddd,0x1e88,0x1f35,0x1fe2,0x2091,0x2141,0x21f3,0x22a5,0x2359,0x240d,0x24c3,0x257a,0x2632,0x26eb,0x27a5,0x285f,0x291b,0x29d8,0x2a95,0x2b53,0x2c12,0x2cd2,0x2d93,0x2e54,0x2f16,0x2fd9,0x309c,0x3160,0x3224,0x32e9,0x33ae,0x3474,0x353b,0x3601,0x36c9,0x3790,0x3858,0x3920,0x39e9,0x3ab1,0x3b7a,0x3c43,0x3d0c,0x3dd6,0x3e9f,0x3f68,0x4032,0x40fb,0x41c5,0x428e,0x4357,0x4420,0x44e9,0x45b2,0x467b,0x4743,0x480b,0x48d3,0x499a,0x4a61,0x4b28,0x4bee,0x4cb3,0x4d79,0x4e3d,0x4f01,0x4fc5,0x5088,0x514a,0x520c,0x52cd,0x538d,0x544c,0x550b,0x55c9,0x5686,0x5742,0x57fd,0x58b8,0x5971,0x5a29,0x5ae1,0x5b97,0x5c4c,0x5d00,0x5db3,0x5e65,0x5f16,0x5fc5,0x6074,0x6121,0x61cc,0x6277,0x6320,0x63c7,0x646e,0x6513,0x65b6,0x6658,0x66f9,0x6798,0x6835,0x68d1,0x696c,0x6a04,0x6a9c,0x6b31,0x6bc5,0x6c57,0x6ce7,0x6d76,0x6e03,0x6e8e,0x6f17,0x6f9f,0x7025,0x70a8,0x712a,0x71aa,0x7228,0x72a5,0x731f,0x7397,0x740d,0x7481,0x74f3,0x7564,0x75d2,0x763e,0x76a7,0x770f,0x7775,0x77d8,0x783a,0x7899,0x78f6,0x7950,0x79a9,0x79ff,0x7a53,0x7aa5,0x7af5,0x7b42,0x7b8d,0x7bd5,0x7c1c,0x7c60,0x7ca1,0x7ce1,0x7d1e,0x7d58,0x7d90,0x7dc6,0x7dfa,0x7e2b,0x7e59,0x7e86,0x7eaf,0x7ed7,0x7efc,0x7f1e,0x7f3e,0x7f5c,0x7f77,0x7f90,0x7fa6,0x7fba,0x7fcb,0x7fda,0x7fe6,0x7ff0,0x7ff8,0x7ffd,0x7fff,0x7fff,0x7ffd,0x7ff8,0x7ff0,0x7fe6,0x7fda,0x7fcb,0x7fba,0x7fa6,0x7f90,0x7f77,0x7f5c,0x7f3e,0x7f1e,0x7efc,0x7ed7,0x7eaf,0x7e86,0x7e59,0x7e2b,0x7dfa,0x7dc6,0x7d90,0x7d58,0x7d1e,0x7ce1,0x7ca1,0x7c60,0x7c1c,0x7bd5,0x7b8d,0x7b42,0x7af5,0x7aa5,0x7a53,0x79ff,0x79a9,0x7950,0x78f6,0x7899,0x783a,0x77d8,0x7775,0x770f,0x76a7,0x763e,0x75d2,0x7564,0x74f3,0x7481,0x740d,0x7397,0x731f,0x72a5,0x7228,0x71aa,0x712a,0x70a8,0x7025,0x6f9f,0x6f17,0x6e8e,0x6e03,0x6d76,0x6ce7,0x6c57,0x6bc5,0x6b31,0x6a9c,0x6a04,0x696c,0x68d1,0x6835,0x6798,0x66f9,0x6658,0x65b6,0x6513,0x646e,0x63c7,0x6320,0x6277,0x61cc,0x6121,0x6074,0x5fc5,0x5f16,0x5e65,0x5db3,0x5d00,0x5c4c,0x5b97,0x5ae1,0x5a29,0x5971,0x58b8,0x57fd,0x5742,0x5686,0x55c9,0x550b,0x544c,0x538d,0x52cd,0x520c,0x514a,0x5088,0x4fc5,0x4f01,0x4e3d,0x4d79,0x4cb3,0x4bee,0x4b28,0x4a61,0x499a,0x48d3,0x480b,0x4743,0x467b,0x45b2,0x44e9,0x4420,0x4357,0x428e,0x41c5,0x40fb, | ||
0x4032,0x3f68,0x3e9f,0x3dd6,0x3d0c,0x3c43,0x3b7a,0x3ab1,0x39e9,0x3920,0x3858,0x3790,0x36c9,0x3601,0x353b,0x3474,0x33ae,0x32e9,0x3224,0x3160,0x309c,0x2fd9,0x2f16,0x2e54,0x2d93,0x2cd2,0x2c12,0x2b53,0x2a95,0x29d8,0x291b,0x285f,0x27a5,0x26eb,0x2632,0x257a,0x24c3,0x240d,0x2359,0x22a5,0x21f3,0x2141,0x2091,0x1fe2,0x1f35,0x1e88,0x1ddd,0x1d34,0x1c8b,0x1be4,0x1b3f,0x1a9a,0x19f8,0x1956,0x18b7,0x1818,0x177c,0x16e0,0x1647,0x15af,0x1519,0x1484,0x13f1,0x1360,0x12d0,0x1242,0x11b6,0x112c,0x10a4,0x101d,0x0f98,0x0f15,0x0e94,0x0e15,0x0d98,0x0d1d,0x0ca4,0x0c2d,0x0bb8,0x0b44,0x0ad3,0x0a64,0x09f7,0x098c,0x0923,0x08bd,0x0858,0x07f6,0x0796,0x0737,0x06dc,0x0682,0x062b,0x05d5,0x0583,0x0532,0x04e3,0x0497,0x044e,0x0406,0x03c1,0x037e,0x033e,0x0300,0x02c4,0x028a,0x0253,0x021f,0x01ec,0x01bd,0x018f,0x0164,0x013c,0x0115,0x00f2,0x00d0,0x00b2,0x0095,0x007b,0x0064,0x004f,0x003c,0x002c,0x001e,0x0013,0x000b,0x0004,0x0001,0x0000}; | ||
// windowing and prescaling | ||
for (size_t i = 0; i < BUF_LEN; i++){ | ||
in[i] = S_MUL(frame[i],win[i]) << 4; | ||
} | ||
|
||
if ((cfg = kiss_fftr_alloc(BUF_LEN, 0/*is_inverse_fft*/, NULL, NULL)) == NULL){ | ||
printf("Not enough memory?\n"); | ||
return 1; | ||
}else{ | ||
kiss_fftr(cfg, in, out); | ||
free(cfg); | ||
} | ||
|
||
for (size_t k = 0; k < FRE_LEN; k++){ | ||
spec[k] = MAG(out[k].r,out[k].i); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static int printMat(char *filename, kiss_fft_scalar *in, size_t N){ | ||
FILE *fp; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So... There is no support currently for storing files. In principal, we could implement a filesystem that ships over to the SD card on the main board, but currently I believe it will always fail on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, that's what I suspected, too. I plan to replace these |
||
|
||
if (! (fp = fopen(filename, "a"))){ | ||
printf("Unable to open %s\n",filename); | ||
return 1; | ||
} | ||
|
||
for (size_t i = 0; i < N-1; i++){ | ||
//fprintf(fp, "%d,",in[i]); | ||
fprintf(fp, "%f,",(double)in[i]/(double)SAMP_MAX); | ||
} | ||
//fprintf(fp, "%d\n",in[N-1]); | ||
fprintf(fp, "%f\n",(double)in[N-1]/(double)SAMP_MAX); | ||
|
||
fclose(fp); | ||
return 0; | ||
} | ||
|
||
static int printMat2(char *filename, size_t *in, size_t N){ | ||
FILE *fp; | ||
|
||
if (! (fp = fopen(filename, "a"))){ | ||
printf("Unable to open %s\n",filename); | ||
return 1; | ||
} | ||
|
||
for (size_t i = 0; i < N-1; i++){ | ||
fprintf(fp, "%zu,",in[i]); | ||
} | ||
fprintf(fp, "%zu\n",in[N-1]); | ||
|
||
fclose(fp); | ||
return 0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the Makefile variable you want to adjust if you want to have a non-flat hierarchy. I believe something like this would include all C files in all subdirectories work:
You could also be more explicit if you only want to include certain subdirectories or files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Amit,
Thank you so much for your help! I tried
but still get
Namely, the Makefile still looks under the
build/
but didn't copy the source files into it?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ugh... yes you are right... the problem is that there is no
lib2fix
subdirectory in thebuild/cortex-m4
directory and our Makefile rule assumes there is (and GCC won't just create one). If you create one after the build fails the first time, it will be able to move past it, but that's not solution.@ppannuto please halp! You are the resident dependency file expert!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a quick follow-up on this motivated by today's phone call. This should be largely fixed by the updates to the Tock build system. I updated signpost a few days ago in the
tock-master
branch, but we're holding off on merging that until after the paper deadline. I'll follow up again on April 11 :)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Pat,
Thanks for the follow-up. And no worries at all, I understand the burden of a paper deadline. We'll get this working soon.
In the meantime, godspeed to your paper!