-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
More fixes and updates Included platt source code
- Loading branch information
Showing
133 changed files
with
6,611 additions
and
203 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
Measurement and simulation framework | ||
Copyright (C) 2020 Marc René Schädler | ||
E-mail: marc.r[email protected] | ||
Author (2020) Marc René Schädler | ||
E-mail: marc.rene[email protected] | ||
|
||
This program is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,9 +3,9 @@ This expert software framework can be used to implement, perform, and simulate ( | |
Measurements and simulations are tightly integrated, such that all implemented measurements can be performed and simulated with the same code base. | ||
The implementations are modular, such that they can be exchanged or used in other contexts. | ||
|
||
Copyright (C) 2020 Marc René Schädler | ||
Author (2020) Marc René Schädler | ||
|
||
E-mail: marc.r[email protected] | ||
E-mail: marc.rene[email protected] | ||
|
||
The repository currently contains a largely undocumented (but fully functional) code drop. | ||
The documentation will be added on demand over time. | ||
|
@@ -48,7 +48,7 @@ However, your audio setup needs to be calibrated before using it. | |
The calibration and compensation tools reside in `loop`. | ||
Please have a look at the `loop/tools/update_configuration.m`. | ||
The parameters for the calibration of your setup can be set there. | ||
Comment out the line which deliberately generates an error. | ||
Comment out the line which deliberately throws an error. | ||
|
||
The provided configuration works well for the Focusrite Scarlett 2i2 sound card and Sennheiser HDA 200 headphones. | ||
`ema/ema.sh` provides a menu for checking the calibration with narrow band noise signals. | ||
|
@@ -90,8 +90,10 @@ Please have a look at the preconfigured example in `data/processing/openMHA9_una | |
All measurements can be combined with all hearing device models, which allows to measure the aided performance in psychoacoustic and speech recognition tasks. | ||
|
||
It is also easy to extend the framework with own JACK plugins for aided measurements. | ||
For example the [PLATT dynamic compressor](https://github.com/m-r-s/platt) will also be available once the corresponding code is available. | ||
|
||
For example the [PLATT dynamic compressor](https://github.com/m-r-s/platt) is also available. | ||
PLATT is an implementation of a [patented dynamic compression scheme](https://www.innowi.de/de/unsere_patente/details/dynamikkompression-uol169) that aims to preserve speech intelligibility. | ||
Its engineered towards the use in hearing devices (it's fast). | ||
Still, it produces high quality signals (it minimizes compression). | ||
|
||
# References | ||
[1] Schädler, M. R., Warzybok, A., Ewert, S. D., Kollmeier, B. (2016) "A simulation framework for auditory discrimination experiments: Revealing the importance of across-frequency processing in speech perception", Journal of the Acoustical Society of America, Volume 139, Issue 5, pp. 2708–2723, URL: http://link.aip.org/link/?JAS/139/2708 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
This directory holds the binary configuration files |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#ifndef __CONSTANTS_H__ | ||
#define __CONSTANTS_H__ | ||
|
||
#define SAMPLERATE 48000 // samplerate in Hz | ||
#define TICKSAMPLES 48 // ~approx 1ms | ||
#define FEEDBACKLENGTH 20 // N * TICKSAMPLES | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
void | ||
feedback(float const * const in1, | ||
float const * const in2, | ||
float * const out, | ||
float * const playbackbuffer, | ||
float const * const feedbackresponse, | ||
int const * const range | ||
) | ||
{ | ||
int feedbacksamples = FEEDBACKLENGTH*TICKSAMPLES; | ||
// Calculate feedback from playback | ||
{ | ||
for (int i=0;i<TICKSAMPLES;i++) { | ||
float feedback_tmp = 0.0; | ||
|
||
// Determine integration ranges | ||
{ | ||
// Range in feedback | ||
int start1 = range[0]; | ||
int stop1 = range[1]; | ||
// Cursor in playbackbuffer | ||
int o1 = tickcount*TICKSAMPLES; | ||
// Range in playbackbuffer | ||
int start2 = (feedbacksamples+o1+i-start1)%feedbacksamples; | ||
int stop2 = (feedbacksamples+o1+i-stop1)%feedbacksamples; | ||
int o2 = start1; | ||
if (stop2 <= start2) { | ||
for (int j=start2;j>=stop2;j--) { | ||
feedback_tmp += playbackbuffer[j] * feedbackresponse[o2]; | ||
o2++; | ||
} | ||
} else { | ||
for (int j=start2;j>=0;j--) { | ||
feedback_tmp += playbackbuffer[j] * feedbackresponse[o2]; | ||
o2++; | ||
} | ||
for (int j=feedbacksamples-1;j>=stop2;j--) { | ||
feedback_tmp += playbackbuffer[j] * feedbackresponse[o2]; | ||
o2++; | ||
} | ||
} | ||
} | ||
// Remove estimated feedback signal from recording | ||
out[i] = in1[i] - feedback_tmp; | ||
} | ||
} | ||
|
||
// Copy new samples to the playbackbuffer | ||
{ | ||
int o1 = tickcount*TICKSAMPLES; | ||
for (int i=0;i<TICKSAMPLES;i++) { | ||
playbackbuffer[o1] = in2[i]; | ||
o1++; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
float feedback1[FEEDBACKLENGTH*TICKSAMPLES] = {0.0}; | ||
float feedback2[FEEDBACKLENGTH*TICKSAMPLES] = {0.0}; | ||
float playbackbuffer1[FEEDBACKLENGTH*TICKSAMPLES] = {0.0}; | ||
float playbackbuffer2[FEEDBACKLENGTH*TICKSAMPLES] = {0.0}; | ||
int range1[2] = {0}; | ||
int range2[2] = {0}; | ||
int tickcount = 0; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
#include <stdio.h> | ||
#include <errno.h> | ||
#include <unistd.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <jack/jack.h> | ||
#include <math.h> | ||
#include "constants.h" | ||
#include "variables.h" | ||
#include "feedback.c" | ||
|
||
#define DEBUG 1 | ||
|
||
jack_port_t *input_port1, *input_port2, *input_port3, *input_port4; | ||
jack_port_t *output_port1, *output_port2; | ||
jack_client_t *client; | ||
|
||
int | ||
process (jack_nframes_t nframes, void *arg) | ||
{ | ||
jack_default_audio_sample_t *in1, *in2, *in3, *in4, *out1, *out2; | ||
|
||
in1 = jack_port_get_buffer (input_port1, nframes); | ||
in2 = jack_port_get_buffer (input_port2, nframes); | ||
in3 = jack_port_get_buffer (input_port3, nframes); | ||
in4 = jack_port_get_buffer (input_port4, nframes); | ||
out1 = jack_port_get_buffer (output_port1, nframes); | ||
out2 = jack_port_get_buffer (output_port2, nframes); | ||
|
||
if (nframes%TICKSAMPLES != 0) { | ||
printf("ERROR! nframes (%i) no multiple of %i\n",nframes,TICKSAMPLES); | ||
return 1; | ||
} else { | ||
for (int i=0; i<nframes; i+=TICKSAMPLES) { | ||
// PROCESS! | ||
feedback(&in1[i], &in3[i], &out1[i], playbackbuffer1, feedback1, range1); | ||
feedback(&in2[i], &in4[i], &out2[i], playbackbuffer2, feedback2, range2); | ||
tickcount = (tickcount+1)%FEEDBACKLENGTH; | ||
} | ||
} | ||
return 0; | ||
} | ||
|
||
/** | ||
* JACK calls this shutdown_callback if the server ever shuts down or | ||
* decides to disconnect the client. | ||
*/ | ||
void | ||
jack_shutdown (void *arg) | ||
{ | ||
exit (1); | ||
} | ||
|
||
int | ||
main (int argc, char *argv[]) | ||
{ | ||
const char *client_name = "abhang"; | ||
const char *server_name = NULL; | ||
jack_options_t options = JackNullOption; | ||
jack_status_t status; | ||
FILE *fp; | ||
|
||
printf("Static Feedback Cancelation\n"); | ||
// Load FEEDBACK | ||
fp = fopen("configuration/feedback1.bin","rb"); | ||
if(fp == NULL) { | ||
printf("Error opening 'configuration/feedback1.bin'\n"); | ||
exit (1); | ||
} | ||
fread(feedback1,sizeof(feedback1),1,fp); | ||
fclose(fp); | ||
fp = fopen("configuration/feedback2.bin","rb"); | ||
if(fp == NULL) { | ||
printf("Error opening 'configuration/feedback2.bin'\n"); | ||
exit (1); | ||
} | ||
fread(feedback2,sizeof(feedback2),1,fp); | ||
fclose(fp); | ||
|
||
// Load FEEDBACK RANGE | ||
fp = fopen("configuration/range1.bin","rb"); | ||
if(fp == NULL) { | ||
printf("Error opening 'configuration/range1.bin'\n"); | ||
exit (1); | ||
} | ||
fread(range1,sizeof(range1),1,fp); | ||
fclose(fp); | ||
fp = fopen("configuration/range2.bin","rb"); | ||
if(fp == NULL) { | ||
printf("Error opening 'configuration/range2.bin'\n"); | ||
exit (1); | ||
} | ||
fread(range2,sizeof(range2),1,fp); | ||
fclose(fp); | ||
|
||
#ifdef DEBUG | ||
printf("\n"); | ||
printf("SAMPLERATE: %i\n",SAMPLERATE); | ||
printf("TICKSAMPLES: %i\n",TICKSAMPLES); | ||
printf("FEEDBACKLENGTH: %i\n",FEEDBACKLENGTH); | ||
printf("\n"); | ||
|
||
for (int i=0;i<TICKSAMPLES*FEEDBACKLENGTH;i++) { | ||
printf("feedback1[%i] = [%.8f]\n",i,feedback1[i]); | ||
} | ||
printf("\n"); | ||
for (int i=0;i<TICKSAMPLES*FEEDBACKLENGTH;i++) { | ||
printf("feedback2[%i] = [%.8f]\n",i,feedback2[i]); | ||
} | ||
printf("range1[0,1] = [%i %i]\n",range1[0],range1[1]); | ||
printf("range2[0,1] = [%i %i]\n",range2[0],range2[1]); | ||
printf("\n"); | ||
|
||
#endif | ||
|
||
/* open a client connection to the JACK server */ | ||
client = jack_client_open (client_name, options, &status, server_name); | ||
if (client == NULL) { | ||
fprintf (stderr, "jack_client_open() failed, " | ||
"status = 0x%2.0x\n", status); | ||
if (status & JackServerFailed) { | ||
fprintf (stderr, "Unable to connect to JACK server\n"); | ||
} | ||
exit (1); | ||
} | ||
if (status & JackServerStarted) { | ||
fprintf (stderr, "JACK server started\n"); | ||
} | ||
if (status & JackNameNotUnique) { | ||
client_name = jack_get_client_name(client); | ||
fprintf (stderr, "unique name `%s' assigned\n", client_name); | ||
} | ||
|
||
// Check if we are in spec | ||
if (jack_get_sample_rate (client) != SAMPLERATE) { | ||
fprintf (stderr, "sample rate (%i!=%i) not supported!\n", jack_get_sample_rate (client), SAMPLERATE); | ||
exit (1); | ||
} | ||
|
||
/* tell the JACK server to call `process()' whenever | ||
there is work to be done. | ||
*/ | ||
|
||
jack_set_process_callback (client, process, 0); | ||
|
||
/* tell the JACK server to call `jack_shutdown()' if | ||
it ever shuts down, either entirely, or if it | ||
just decides to stop calling us. | ||
*/ | ||
|
||
jack_on_shutdown (client, jack_shutdown, 0); | ||
|
||
/* display the current sample rate. | ||
*/ | ||
|
||
printf ("engine sample rate: %" PRIu32 "\n", | ||
jack_get_sample_rate (client)); | ||
|
||
/* create two ports */ | ||
|
||
input_port1 = jack_port_register (client, "input_1", | ||
JACK_DEFAULT_AUDIO_TYPE, | ||
JackPortIsInput, 0); | ||
input_port2 = jack_port_register (client, "input_2", | ||
JACK_DEFAULT_AUDIO_TYPE, | ||
JackPortIsInput, 0); | ||
input_port3 = jack_port_register (client, "input_3", | ||
JACK_DEFAULT_AUDIO_TYPE, | ||
JackPortIsInput, 0); | ||
input_port4 = jack_port_register (client, "input_4", | ||
JACK_DEFAULT_AUDIO_TYPE, | ||
JackPortIsInput, 0); | ||
|
||
output_port1 = jack_port_register (client, "output_1", | ||
JACK_DEFAULT_AUDIO_TYPE, | ||
JackPortIsOutput, 0); | ||
output_port2 = jack_port_register (client, "output_2", | ||
JACK_DEFAULT_AUDIO_TYPE, | ||
JackPortIsOutput, 0); | ||
|
||
if ((input_port1 == NULL) || (input_port2 == NULL) || (input_port3 == NULL) || (input_port4 == NULL) || (output_port1 == NULL) || (output_port2 == NULL) ) { | ||
fprintf(stderr, "no more JACK ports available\n"); | ||
exit (1); | ||
} | ||
|
||
/* Tell the JACK server that we are ready to roll. Our | ||
* process() callback will start running now. */ | ||
|
||
if (jack_activate (client)) { | ||
fprintf (stderr, "cannot activate client"); | ||
exit (1); | ||
} | ||
|
||
/* keep running until stopped by the user */ | ||
|
||
sleep (-1); | ||
|
||
/* this is never reached but if the program | ||
had some other way to exit besides being killed, | ||
they would be important to call. | ||
*/ | ||
|
||
jack_client_close (client); | ||
exit (0); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../configuration/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../core/constants.h |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../core/feedback.c |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../core/variables.h |
Oops, something went wrong.