noyes 0.9.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/bin/nrec +5 -0
- data/lib/{c_impl → cext}/array_list.c +25 -25
- data/lib/cext/bent_cent_marker.c +55 -0
- data/lib/{c_impl/n_array_list.c → cext/c_array_list.c} +12 -12
- data/lib/cext/c_array_list.h +18 -0
- data/lib/{c_impl/n_bent_cent_marker.c → cext/c_bent_cent_marker.c} +13 -11
- data/lib/{c_impl/n_dft.c → cext/c_dft.c} +3 -3
- data/lib/{c_impl/n_discrete_cosine_transform.c → cext/c_discrete_cosine_transform.c} +5 -5
- data/lib/{c_impl/n_hamming_window.c → cext/c_hamming_window.c} +5 -5
- data/lib/{c_impl/n_live_cmn.c → cext/c_live_cmn.c} +5 -5
- data/lib/{c_impl/n_log_compressor.c → cext/c_log_compressor.c} +5 -5
- data/lib/cext/c_matrix.c +90 -0
- data/lib/{c_impl/n_mel_filter.c → cext/c_mel_filter.c} +13 -11
- data/lib/cext/c_mfcc_16x8.c +57 -0
- data/lib/{c_impl/noyes.h → cext/c_noyes.h} +50 -47
- data/lib/{c_impl/n_power_spec.c → cext/c_power_spec.c} +6 -6
- data/lib/{c_impl/n_preemphasis.c → cext/c_preemphasis.c} +4 -4
- data/lib/{c_impl/n_segmenter.c → cext/c_segmenter.c} +17 -11
- data/lib/cext/c_speech_trimmer.c +126 -0
- data/lib/{c_impl → cext}/discrete_cosine_transform.c +18 -20
- data/lib/{c_impl → cext}/hamming_window.c +11 -13
- data/lib/{c_impl → cext}/live_cmn.c +11 -14
- data/lib/{c_impl → cext}/log_compressor.c +11 -14
- data/lib/{c_impl → cext}/mel_filter.c +13 -17
- data/lib/cext/mfcc_16x8.c +36 -0
- data/lib/{c_impl → cext}/power_spectrum.c +10 -12
- data/lib/{c_impl → cext}/preemphasis.c +10 -13
- data/lib/{c_impl/noyes_c.c → cext/r_noyes.c} +12 -12
- data/lib/{c_impl/rnoyes.h → cext/r_noyes.h} +6 -6
- data/lib/{c_impl → cext}/segmenter.c +10 -13
- data/lib/{c_impl → cext}/speech_trimmer.c +23 -23
- data/lib/common/noyes_dsl.rb +3 -0
- data/lib/common/ruby_ext.rb +9 -0
- data/lib/noyes.rb +13 -0
- data/lib/noyes_c.rb +23 -1
- data/lib/noyes_java.rb +5 -0
- data/lib/ruby_impl/compression.rb +214 -0
- data/lib/ruby_impl/dct.rb +2 -2
- data/lib/ruby_impl/live_cmn.rb +4 -4
- data/lib/ruby_impl/mel_filter.rb +9 -9
- data/lib/ruby_impl/segment.rb +13 -2
- data/lib/ruby_impl/speech_trimmer.rb +3 -1
- data/ship/noyes.jar +0 -0
- metadata +36 -34
- data/lib/c_impl/bent_cent_marker.c +0 -36
- data/lib/c_impl/fast_8k_mfcc.c +0 -39
- data/lib/c_impl/n_array_list.h +0 -18
- data/lib/c_impl/n_fast_8k_mfcc.c +0 -55
- data/lib/c_impl/n_matrix.c +0 -72
- data/lib/c_impl/n_speech_trimmer.c +0 -96
- /data/lib/{c_impl → cext}/extconf.rb +0 -0
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
1.0.0
|
data/bin/nrec
CHANGED
@@ -107,6 +107,11 @@ def recognize file, options
|
|
107
107
|
send_incremental_features file, client, client, bits, rate
|
108
108
|
end
|
109
109
|
end
|
110
|
+
rescue Errno::ECONNREFUSED
|
111
|
+
puts "Connection refused."
|
112
|
+
puts "Possibly the IP address and port are incorrect."
|
113
|
+
puts "Or maybe the server is down. Contact Talkhouse if this persists."
|
114
|
+
exit 2
|
110
115
|
end
|
111
116
|
|
112
117
|
ARGV.each do |file|
|
@@ -1,58 +1,58 @@
|
|
1
1
|
#include "ruby.h"
|
2
|
-
#include "
|
3
|
-
#include "
|
2
|
+
#include "c_noyes.h"
|
3
|
+
#include "r_noyes.h"
|
4
4
|
|
5
5
|
static int id_push;
|
6
6
|
|
7
7
|
VALUE cArrayList;
|
8
8
|
|
9
|
-
static void
|
10
|
-
|
9
|
+
static void free_clist(void *p) {
|
10
|
+
clist_free(p);
|
11
11
|
}
|
12
12
|
|
13
13
|
static VALUE t_init(VALUE self) {
|
14
|
-
|
15
|
-
VALUE stv = Data_Wrap_Struct(cArrayList, 0,
|
16
|
-
rb_iv_set(self, "@
|
14
|
+
Clist *st = clist_new();
|
15
|
+
VALUE stv = Data_Wrap_Struct(cArrayList, 0, free_clist, st);
|
16
|
+
rb_iv_set(self, "@clist", stv);
|
17
17
|
return self;
|
18
18
|
}
|
19
19
|
|
20
20
|
static VALUE t_size(VALUE self) {
|
21
|
-
|
22
|
-
VALUE arrayv = rb_iv_get(self, "@
|
23
|
-
Data_Get_Struct(arrayv,
|
24
|
-
return INT2FIX(
|
21
|
+
Clist *array;
|
22
|
+
VALUE arrayv = rb_iv_get(self, "@clist");
|
23
|
+
Data_Get_Struct(arrayv, Clist, array);
|
24
|
+
return INT2FIX(clist_size(array));
|
25
25
|
}
|
26
26
|
|
27
27
|
static VALUE t_add(VALUE self, VALUE obj) {
|
28
|
-
|
29
|
-
VALUE arrayv = rb_iv_get(self, "@
|
30
|
-
Data_Get_Struct(arrayv,
|
31
|
-
|
28
|
+
Clist *array;
|
29
|
+
VALUE arrayv = rb_iv_get(self, "@clist");
|
30
|
+
Data_Get_Struct(arrayv, Clist, array);
|
31
|
+
clist_add(array, (void*)obj);
|
32
32
|
return Qnil;
|
33
33
|
}
|
34
34
|
|
35
35
|
static VALUE t_get(VALUE self, VALUE obj) {
|
36
|
-
|
37
|
-
VALUE arrayv = rb_iv_get(self, "@
|
38
|
-
Data_Get_Struct(arrayv,
|
39
|
-
return (VALUE)
|
36
|
+
Clist *array;
|
37
|
+
VALUE arrayv = rb_iv_get(self, "@clist");
|
38
|
+
Data_Get_Struct(arrayv, Clist, array);
|
39
|
+
return (VALUE)clist_get(array, FIX2INT(obj));
|
40
40
|
}
|
41
41
|
|
42
42
|
static VALUE t_remove(VALUE self, VALUE start, VALUE finish) {
|
43
|
-
|
44
|
-
VALUE arrayv = rb_iv_get(self, "@
|
45
|
-
Data_Get_Struct(arrayv,
|
43
|
+
Clist *array;
|
44
|
+
VALUE arrayv = rb_iv_get(self, "@clist");
|
45
|
+
Data_Get_Struct(arrayv, Clist, array);
|
46
46
|
int b = FIX2INT(start);
|
47
47
|
int e = FIX2INT(finish);
|
48
|
-
if (
|
49
|
-
int s =
|
48
|
+
if (clist_remove(array, b, e)) {
|
49
|
+
int s = clist_size(array);
|
50
50
|
rb_raise(rb_eArgError, "start = %d, finish = %d with size = %d", b, e, s);
|
51
51
|
}
|
52
52
|
return Qnil;
|
53
53
|
}
|
54
54
|
|
55
|
-
void
|
55
|
+
void Init_clist() {
|
56
56
|
VALUE m_noyes_c = rb_define_module("NoyesC");
|
57
57
|
cArrayList = rb_define_class_under(m_noyes_c, "ArrayList", rb_cObject);
|
58
58
|
rb_define_method(cArrayList, "initialize", t_init, 0);
|
@@ -0,0 +1,55 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include "c_noyes.h"
|
3
|
+
#include "r_noyes.h"
|
4
|
+
|
5
|
+
VALUE cBentCentMarker;
|
6
|
+
|
7
|
+
static void _bent_cent_marker_free(void *p) {
|
8
|
+
bent_cent_marker_free(p);
|
9
|
+
}
|
10
|
+
|
11
|
+
static VALUE t_init(VALUE self, VALUE args) {
|
12
|
+
double adjustment = 0.003;
|
13
|
+
double average_number = 1.0;
|
14
|
+
double background = 100.0;
|
15
|
+
double level = 0.0;
|
16
|
+
double min_signal = 0.0;
|
17
|
+
double threshold = 10.0;
|
18
|
+
int len = RARRAY_LEN(args);
|
19
|
+
if (len > 0)
|
20
|
+
threshold = NUM2INT(rb_ary_entry(args, 0));
|
21
|
+
if (len > 1)
|
22
|
+
adjustment = NUM2INT(rb_ary_entry(args, 1));
|
23
|
+
if (len > 2)
|
24
|
+
average_number = NUM2INT(rb_ary_entry(args, 2));
|
25
|
+
if (len > 3)
|
26
|
+
background = NUM2INT(rb_ary_entry(args, 3));
|
27
|
+
if (len > 4)
|
28
|
+
level = NUM2INT(rb_ary_entry(args, 4));
|
29
|
+
if (len > 5)
|
30
|
+
min_signal = NUM2INT(rb_ary_entry(args, 5));
|
31
|
+
|
32
|
+
BentCentMarker *pre = bent_cent_marker_new(threshold, adjustment,
|
33
|
+
average_number, background, level, min_signal);
|
34
|
+
|
35
|
+
VALUE prev = Data_Wrap_Struct(cBentCentMarker, 0, _bent_cent_marker_free, pre);
|
36
|
+
rb_iv_set(self, "@bent_cent_marker", prev);
|
37
|
+
return self;
|
38
|
+
}
|
39
|
+
|
40
|
+
static VALUE t_left_shift(VALUE self, VALUE obj) {
|
41
|
+
Carr *M = r2carr(obj);
|
42
|
+
BentCentMarker *pre;
|
43
|
+
VALUE prev = rb_iv_get(self, "@bent_cent_marker");
|
44
|
+
Data_Get_Struct(prev, BentCentMarker, pre);
|
45
|
+
int res = bent_cent_marker_apply(pre, M);
|
46
|
+
carr_free(M);
|
47
|
+
return res ? Qtrue : Qfalse;
|
48
|
+
}
|
49
|
+
|
50
|
+
void Init_bent_cent_marker() {
|
51
|
+
VALUE m_noyes_c = rb_define_module("NoyesC");
|
52
|
+
cBentCentMarker = rb_define_class_under(m_noyes_c, "BentCentMarker", rb_cObject);
|
53
|
+
rb_define_method(cBentCentMarker, "initialize", t_init, -2);
|
54
|
+
rb_define_method(cBentCentMarker, "<<", t_left_shift, 1);
|
55
|
+
}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#include <string.h>
|
2
2
|
#include <stdlib.h>
|
3
3
|
#include <stdio.h>
|
4
|
-
#include "
|
4
|
+
#include "c_array_list.h"
|
5
5
|
|
6
6
|
#define NLIST_INITIAL_CAPACITY 10
|
7
7
|
#define NLIST_DELTA_CAPACITY 10
|
@@ -10,22 +10,22 @@
|
|
10
10
|
#undef FALSE
|
11
11
|
#define FALSE 0
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
self = malloc(sizeof(
|
13
|
+
Clist * clist_new() {
|
14
|
+
Clist * self;
|
15
|
+
self = malloc(sizeof(Clist));
|
16
16
|
self->capacity = NLIST_INITIAL_CAPACITY;
|
17
17
|
self->data = malloc(sizeof(void*) * self->capacity);
|
18
18
|
self->size = 0;
|
19
19
|
return self;
|
20
20
|
}
|
21
21
|
|
22
|
-
void
|
22
|
+
void clist_free(Clist * self) {
|
23
23
|
free(self->data);
|
24
24
|
free(self);
|
25
25
|
}
|
26
26
|
|
27
|
-
int
|
28
|
-
int old_size =
|
27
|
+
int clist_add(Clist * self, void * object) {
|
28
|
+
int old_size = clist_size(self);
|
29
29
|
int new_capacity;
|
30
30
|
void ** new_data;
|
31
31
|
|
@@ -42,7 +42,7 @@ int n_list_add(NList * self, void * object) {
|
|
42
42
|
return TRUE;
|
43
43
|
}
|
44
44
|
|
45
|
-
int
|
45
|
+
int clist_remove(Clist * self, int start, int finish) {
|
46
46
|
if (start > finish || finish > self->size)
|
47
47
|
return 1;
|
48
48
|
|
@@ -57,16 +57,16 @@ int n_list_remove(NList * self, int start, int finish) {
|
|
57
57
|
return 0;
|
58
58
|
}
|
59
59
|
|
60
|
-
void *
|
60
|
+
void * clist_get(const Clist * self, const int index) {
|
61
61
|
if (index < 0 || index > self->size)
|
62
62
|
return NULL;
|
63
63
|
return self->data[index];
|
64
64
|
}
|
65
65
|
|
66
|
-
int
|
67
|
-
return 0 ==
|
66
|
+
int clist_is_empty(const Clist * self) {
|
67
|
+
return 0 == clist_size(self);
|
68
68
|
}
|
69
69
|
|
70
|
-
int
|
70
|
+
int clist_size(const Clist * self) {
|
71
71
|
return self->size;
|
72
72
|
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#ifndef _N_ARRAY_LIST_H_
|
2
|
+
#define _N_ARRAY_LIST_H_
|
3
|
+
|
4
|
+
typedef struct {
|
5
|
+
int capacity;
|
6
|
+
void **data;
|
7
|
+
int size;
|
8
|
+
} Clist;
|
9
|
+
|
10
|
+
Clist * clist_new();
|
11
|
+
void clist_free(Clist * self);
|
12
|
+
int clist_size(const Clist * self);
|
13
|
+
int clist_add(Clist * self, void * object);
|
14
|
+
int clist_remove(Clist * self, int start, int finish);
|
15
|
+
void * clist_get(const Clist * self, const int index);
|
16
|
+
int clist_is_empty(const Clist * self);
|
17
|
+
|
18
|
+
#endif
|
@@ -1,23 +1,25 @@
|
|
1
|
-
#include "
|
1
|
+
#include "c_noyes.h"
|
2
2
|
#include "math.h"
|
3
3
|
#include "stdlib.h"
|
4
4
|
|
5
|
-
BentCentMarker *
|
5
|
+
BentCentMarker * bent_cent_marker_new(double threshold, double adjustment,
|
6
|
+
double average_number, double background,
|
7
|
+
double level, double min_signal) {
|
6
8
|
BentCentMarker *self = malloc(sizeof(BentCentMarker));
|
7
|
-
self->adjustment =
|
8
|
-
self->average_number =
|
9
|
-
self->background =
|
10
|
-
self->level =
|
11
|
-
self->min_signal =
|
12
|
-
self->threshold =
|
9
|
+
self->adjustment = adjustment;
|
10
|
+
self->average_number = average_number;
|
11
|
+
self->background = background;
|
12
|
+
self->level = level;
|
13
|
+
self->min_signal = min_signal;
|
14
|
+
self->threshold = threshold;
|
13
15
|
return self;
|
14
16
|
}
|
15
17
|
|
16
|
-
void
|
18
|
+
void bent_cent_marker_free(BentCentMarker *self) {
|
17
19
|
free(self);
|
18
20
|
}
|
19
21
|
|
20
|
-
double bent_cent_log_rms(BentCentMarker *self,
|
22
|
+
double bent_cent_log_rms(BentCentMarker *self, Carr *pcm) {
|
21
23
|
double sum_of_squares = 0.0;
|
22
24
|
int i;
|
23
25
|
for (i=0;i<pcm->rows;++i) {
|
@@ -28,7 +30,7 @@ double bent_cent_log_rms(BentCentMarker *self, NMatrix1 *pcm) {
|
|
28
30
|
return log(rms) * 20;
|
29
31
|
}
|
30
32
|
|
31
|
-
int bent_cent_marker_apply(BentCentMarker *self,
|
33
|
+
int bent_cent_marker_apply(BentCentMarker *self, Carr *pcm) {
|
32
34
|
int is_speech = 0;
|
33
35
|
double current = bent_cent_log_rms(self, pcm);
|
34
36
|
if (current >= self->min_signal) {
|
@@ -1,15 +1,15 @@
|
|
1
|
-
#include "
|
1
|
+
#include "c_noyes.h"
|
2
2
|
#include "stdlib.h"
|
3
3
|
#include "memory.h"
|
4
4
|
#include "math.h"
|
5
5
|
#include "stdio.h"
|
6
6
|
|
7
|
-
|
7
|
+
Cmat * dft(double * data, int datalen, int size) {
|
8
8
|
if (datalen> size) {
|
9
9
|
fprintf(stderr,"Size(%d) must be larger than data length(%d)", size, datalen);
|
10
10
|
return NULL;
|
11
11
|
}
|
12
|
-
|
12
|
+
Cmat *M = cmat_new(2, size);
|
13
13
|
double * real = M->data[0];
|
14
14
|
double * imag = M->data[1];
|
15
15
|
int j=0,i;
|
@@ -1,7 +1,7 @@
|
|
1
|
-
#include "
|
1
|
+
#include "c_noyes.h"
|
2
2
|
#include "math.h"
|
3
3
|
|
4
|
-
DiscreteCosineTransform *
|
4
|
+
DiscreteCosineTransform * dct_new(int rows, int cols) {
|
5
5
|
DiscreteCosineTransform *dct = malloc(sizeof(DiscreteCosineTransform));
|
6
6
|
dct->melcos = malloc(rows *sizeof(double*));
|
7
7
|
dct->rows = rows;
|
@@ -18,7 +18,7 @@ DiscreteCosineTransform * new_dct(int rows, int cols) {
|
|
18
18
|
return dct;
|
19
19
|
}
|
20
20
|
|
21
|
-
void
|
21
|
+
void dct_free(DiscreteCosineTransform *dct) {
|
22
22
|
int i;
|
23
23
|
for (i=0;i<dct->rows;++i) {
|
24
24
|
free(dct->melcos[i]);
|
@@ -27,8 +27,8 @@ void free_dct(DiscreteCosineTransform *dct) {
|
|
27
27
|
free(dct);
|
28
28
|
}
|
29
29
|
|
30
|
-
|
31
|
-
|
30
|
+
Cmat * dct_apply(DiscreteCosineTransform *self, Cmat *data) {
|
31
|
+
Cmat *M = cmat_new(data->rows, self->rows);
|
32
32
|
int i,j,k;
|
33
33
|
for (i=0;i<M->rows;++i) {
|
34
34
|
for (j=0;j<M->cols;++j) {
|
@@ -1,7 +1,7 @@
|
|
1
|
-
#include "
|
1
|
+
#include "c_noyes.h"
|
2
2
|
#include "math.h"
|
3
3
|
|
4
|
-
HammingWindow *
|
4
|
+
HammingWindow * hamming_window_new(int window_size) {
|
5
5
|
HammingWindow *hw = malloc(sizeof(HammingWindow));
|
6
6
|
hw->buf = malloc(window_size * sizeof(double));
|
7
7
|
hw->buflen = window_size;
|
@@ -13,13 +13,13 @@ HammingWindow * new_hamming_window(int window_size) {
|
|
13
13
|
return hw;
|
14
14
|
}
|
15
15
|
|
16
|
-
void
|
16
|
+
void hamming_window_free(HammingWindow *hw) {
|
17
17
|
free(hw->buf);
|
18
18
|
free(hw);
|
19
19
|
}
|
20
20
|
|
21
|
-
|
22
|
-
|
21
|
+
Cmat * hamming_window_apply(HammingWindow *self, Cmat* N) {
|
22
|
+
Cmat *M = cmat_new(N->rows, N->cols);
|
23
23
|
int i,j;
|
24
24
|
for (i=0;i<N->rows;++i) {
|
25
25
|
for (j=0;j<N->cols;++j) {
|
@@ -1,8 +1,8 @@
|
|
1
|
-
#include "
|
1
|
+
#include "c_noyes.h"
|
2
2
|
#include "stdlib.h"
|
3
3
|
#include "stdio.h"
|
4
4
|
|
5
|
-
LiveCMN *
|
5
|
+
LiveCMN * live_cmn_new(int dimensions, double init_mean, int window_size,
|
6
6
|
int shift) {
|
7
7
|
LiveCMN *cmn = malloc(sizeof(LiveCMN));
|
8
8
|
cmn->init_mean = init_mean;
|
@@ -16,7 +16,7 @@ LiveCMN * new_live_cmn(int dimensions, double init_mean, int window_size,
|
|
16
16
|
return cmn;
|
17
17
|
}
|
18
18
|
|
19
|
-
void
|
19
|
+
void live_cmn_free(LiveCMN *cmn) {
|
20
20
|
free(cmn->sums);
|
21
21
|
free(cmn->means);
|
22
22
|
free(cmn);
|
@@ -51,12 +51,12 @@ static void live_cmn_update(LiveCMN *self) {
|
|
51
51
|
}
|
52
52
|
}
|
53
53
|
|
54
|
-
|
54
|
+
Cmat *live_cmn_apply(LiveCMN *self, Cmat *dct) {
|
55
55
|
if (dct->cols != self->dimensions) {
|
56
56
|
fprintf(stderr, "Wrong number of dimensions in live_cmn_apply\n");
|
57
57
|
return NULL;
|
58
58
|
}
|
59
|
-
|
59
|
+
Cmat *cmn = cmat_new(dct->rows, dct->cols);
|
60
60
|
int i,j;
|
61
61
|
for (i=0;i<dct->rows;++i) {
|
62
62
|
for (j=0;j<dct->cols;++j) {
|
@@ -1,16 +1,16 @@
|
|
1
|
-
#include "
|
1
|
+
#include "c_noyes.h"
|
2
2
|
#include "math.h"
|
3
3
|
|
4
|
-
LogCompressor *
|
4
|
+
LogCompressor * log_compressor_new(double log_zero) {
|
5
5
|
return malloc(sizeof(LogCompressor));
|
6
6
|
}
|
7
7
|
|
8
|
-
void
|
8
|
+
void log_compressor_free(LogCompressor *lc) {
|
9
9
|
free(lc);
|
10
10
|
}
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
Cmat * log_compressor_apply(LogCompressor *self, Cmat *data) {
|
13
|
+
Cmat *M = cmat_new(data->rows, data->cols);
|
14
14
|
int i, j;
|
15
15
|
for (i=0;i<M->rows;++i) {
|
16
16
|
for (j=0;j<M->cols;++j) {
|
data/lib/cext/c_matrix.c
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
#include "c_noyes.h"
|
2
|
+
#include "memory.h"
|
3
|
+
|
4
|
+
// A 2 dimensional dense rectangular matrix "class".
|
5
|
+
Cmat *cmat_new(int rows, int cols) {
|
6
|
+
Cmat *M = malloc(sizeof(Cmat));
|
7
|
+
M->data = malloc(rows * sizeof(double*));
|
8
|
+
int i;
|
9
|
+
for (i=0;i<rows;++i) {
|
10
|
+
M->data[i] = malloc(cols * sizeof(double));
|
11
|
+
}
|
12
|
+
M->rows = rows;
|
13
|
+
M->cols = cols;
|
14
|
+
return M;
|
15
|
+
}
|
16
|
+
|
17
|
+
void cmat_free(Cmat *M) {
|
18
|
+
if (M) {
|
19
|
+
int i;
|
20
|
+
for (i=0;i<M->rows;++i) {
|
21
|
+
free(M->data[i]);
|
22
|
+
}
|
23
|
+
free(M->data);
|
24
|
+
free(M);
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
// A 1 dimensional matrix "class".
|
29
|
+
Carr *carr_new(int rows) {
|
30
|
+
Carr *M = malloc(sizeof(Carr));
|
31
|
+
M->data = malloc(rows * sizeof(double));
|
32
|
+
M->rows = rows;
|
33
|
+
return M;
|
34
|
+
}
|
35
|
+
|
36
|
+
void carr_free(Carr *M) {
|
37
|
+
if (M) {
|
38
|
+
free(M->data);
|
39
|
+
free(M);
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
// Converts a rectangular matrix to a list of one dimensional matrices.
|
44
|
+
// Simultaneously frees the original rectangular matrix. Actually, the matrix
|
45
|
+
// does not have to be rectangular. Column sizes may vary.
|
46
|
+
Carr ** mat2arrs(Cmat *M) {
|
47
|
+
Carr **arrs = malloc(sizeof(Carr*) * M->rows);
|
48
|
+
int i;
|
49
|
+
for (i=0;i<M->rows;++i) {
|
50
|
+
arrs[i] = malloc(sizeof(Carr));
|
51
|
+
arrs[i]->data = M->data[i];
|
52
|
+
arrs[i]->rows = M->cols;
|
53
|
+
}
|
54
|
+
free(M->data);
|
55
|
+
free(M);
|
56
|
+
return arrs;
|
57
|
+
}
|
58
|
+
|
59
|
+
// Creates an array by appending columns of a rectangular matrix. Does not
|
60
|
+
// delete the original matrix.
|
61
|
+
Carr *cmat_flatten(Cmat *M) {
|
62
|
+
Carr *flat = carr_new(M->rows * M->cols);
|
63
|
+
int i;
|
64
|
+
for (i=0;i<M->rows; ++i)
|
65
|
+
memcpy(flat->data + (M->cols * i), M->data[i], sizeof(double) * M->cols);
|
66
|
+
|
67
|
+
return flat;
|
68
|
+
}
|
69
|
+
|
70
|
+
// Converts an array of one dimensional arrays into a rectangular matrix. It
|
71
|
+
// frees these arrays in the process. All arrays must have the same length.
|
72
|
+
Cmat * arrs2mat(Carr **array, int size) {
|
73
|
+
if (size == 0) {
|
74
|
+
if (array != NULL)
|
75
|
+
free(array);
|
76
|
+
return NULL;
|
77
|
+
}
|
78
|
+
Cmat *mat = malloc(sizeof(Cmat));
|
79
|
+
mat->data = malloc(sizeof(double*) * size);
|
80
|
+
mat->rows = size;
|
81
|
+
mat->cols = array[0]->rows;
|
82
|
+
int i;
|
83
|
+
for (i=0; i<size; ++i) {
|
84
|
+
mat->data[i] = array[i]->data;
|
85
|
+
free(array[i]);
|
86
|
+
}
|
87
|
+
free(array);
|
88
|
+
|
89
|
+
return mat;
|
90
|
+
}
|
@@ -1,21 +1,21 @@
|
|
1
|
-
#include "
|
1
|
+
#include "c_noyes.h"
|
2
2
|
#include "stdlib.h"
|
3
3
|
#include "memory.h"
|
4
4
|
#include "math.h"
|
5
5
|
|
6
|
-
|
6
|
+
Carr * make_filter(double left, double center, double right,
|
7
7
|
double initFreq, double delta);
|
8
8
|
|
9
9
|
MelFilter * new_mel_filter(int srate, int nfft, int nfilt, int lowerf, int upperf) {
|
10
10
|
MelFilter *mf = malloc(sizeof(MelFilter));
|
11
|
-
|
11
|
+
Cmat *params = make_bank_parameters(srate, nfft, nfilt, lowerf, upperf);
|
12
12
|
mf->len = params->rows;
|
13
13
|
mf->indices = malloc(params->rows * sizeof(int));
|
14
14
|
mf->weights = malloc(params->rows * sizeof(double*));
|
15
15
|
mf->weightlens = malloc(params->rows * sizeof(int));
|
16
16
|
int i;
|
17
17
|
for (i=0; i<params->rows;++i) {
|
18
|
-
|
18
|
+
Carr * temp = make_filter(params->data[i][0], params->data[i][1],
|
19
19
|
params->data[i][2], params->data[i][3],
|
20
20
|
params->data[i][4]);
|
21
21
|
mf->indices[i] = round(temp->data[0]);
|
@@ -27,12 +27,14 @@ MelFilter * new_mel_filter(int srate, int nfft, int nfilt, int lowerf, int upper
|
|
27
27
|
double foo = temp->data[j+1];
|
28
28
|
mf->weights[i][j] = foo;
|
29
29
|
}
|
30
|
+
carr_free(temp);
|
30
31
|
}
|
32
|
+
cmat_free(params);
|
31
33
|
return mf;
|
32
34
|
}
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
+
Cmat * mel_filter_apply(MelFilter* self, Cmat * power_spectrum) {
|
37
|
+
Cmat *melbanks = cmat_new(power_spectrum->rows, self->len);
|
36
38
|
int i;
|
37
39
|
for (i=0;i<power_spectrum->rows; ++i) {
|
38
40
|
double * spectrum = power_spectrum->data[i];
|
@@ -55,7 +57,7 @@ NMatrix * mel_filter_apply(MelFilter* self, NMatrix * power_spectrum) {
|
|
55
57
|
return melbanks;
|
56
58
|
}
|
57
59
|
|
58
|
-
void
|
60
|
+
void mel_filter_free(MelFilter* mf) {
|
59
61
|
int i;
|
60
62
|
for (i=0;i<mf->len;++i) {
|
61
63
|
free(mf->weights[i]);
|
@@ -85,7 +87,7 @@ double melinv(double m) {
|
|
85
87
|
// return result;
|
86
88
|
//}
|
87
89
|
|
88
|
-
|
90
|
+
Cmat *make_bank_parameters(double srate, int nfft, int nfilt,
|
89
91
|
double lowerf, double upperf) {
|
90
92
|
double * leftEdge = alloca(nfilt*sizeof(double));
|
91
93
|
double * rightEdge = alloca(nfilt*sizeof(double));
|
@@ -111,7 +113,7 @@ NMatrix *make_bank_parameters(double srate, int nfft, int nfilt,
|
|
111
113
|
nextEdgeMel += deltaFreqMel;
|
112
114
|
double nextEdge = melinv(nextEdgeMel);
|
113
115
|
rightEdge[nfilt-1] = determine_bin(nextEdge, deltaFreq);
|
114
|
-
|
116
|
+
Cmat *fparams = cmat_new(nfilt, 5);
|
115
117
|
for (i=0;i<nfilt;++i) {
|
116
118
|
double initialFreqBin = determine_bin(leftEdge[i], deltaFreq);
|
117
119
|
if (initialFreqBin < leftEdge[i]) {
|
@@ -128,10 +130,10 @@ NMatrix *make_bank_parameters(double srate, int nfft, int nfilt,
|
|
128
130
|
|
129
131
|
// Returns an array of weights with one additional element at the zero
|
130
132
|
// location containing the starting index.
|
131
|
-
|
133
|
+
Carr * make_filter(double left, double center, double right,
|
132
134
|
double initFreq, double delta) {
|
133
135
|
int nElements = round((right - left)/ delta + 1);
|
134
|
-
|
136
|
+
Carr * filter = carr_new(nElements + 1);
|
135
137
|
double height=1.0;
|
136
138
|
double leftSlope = height / (center - left);
|
137
139
|
double rightSlope = height / (center - right);
|
@@ -0,0 +1,57 @@
|
|
1
|
+
#include "c_noyes.h"
|
2
|
+
|
3
|
+
// Mfcc16x8 is a convenience class that encapsulates an entire front end that
|
4
|
+
// takes 16kHz audio and transforms it to work with 8kHz models.
|
5
|
+
Mfcc16x8 * mfcc_16x8_new() {
|
6
|
+
double factor = 0.97;
|
7
|
+
int nfilt = 32;
|
8
|
+
int min_freq = 200;
|
9
|
+
int max_freq = 3700;
|
10
|
+
int nfft = 256*2;
|
11
|
+
int freq = 8000*2;
|
12
|
+
int shift = 80*2;
|
13
|
+
int frame_size = 205*2;
|
14
|
+
double log_zero = -0.00001;
|
15
|
+
int dimensions=13;
|
16
|
+
int cmn_init_mean=45.0;
|
17
|
+
int cmn_window_size=100;
|
18
|
+
int cmn_shift=160;
|
19
|
+
|
20
|
+
Mfcc16x8 *self = malloc(sizeof(Mfcc16x8));
|
21
|
+
self->pre = new_preemphasizer(factor);
|
22
|
+
self->seg = new_segmenter(frame_size, shift);
|
23
|
+
self->ham = hamming_window_new(frame_size);
|
24
|
+
self->pow = new_power_spectrum(nfft);
|
25
|
+
self->mel = new_mel_filter(freq, nfft, nfilt, min_freq, max_freq);
|
26
|
+
self->log = log_compressor_new(log_zero);
|
27
|
+
self->dct = dct_new(dimensions, nfilt);
|
28
|
+
self->cmn = live_cmn_new(dimensions, cmn_init_mean, cmn_window_size, cmn_shift);
|
29
|
+
return self;
|
30
|
+
}
|
31
|
+
|
32
|
+
void mfcc_16x8_free(Mfcc16x8 *self) {
|
33
|
+
free(self->seg);
|
34
|
+
free(self->ham);
|
35
|
+
free(self->pow);
|
36
|
+
free(self->mel);
|
37
|
+
free(self->log);
|
38
|
+
free(self->dct);
|
39
|
+
free(self->cmn);
|
40
|
+
free(self);
|
41
|
+
}
|
42
|
+
|
43
|
+
Cmat *mfcc_16x8_apply(Mfcc16x8 *self, Carr * data) {
|
44
|
+
Cmat *M = NULL;
|
45
|
+
Cmat *N = NULL;
|
46
|
+
Carr *data1 = preemphasizer_apply(self->pre, data);
|
47
|
+
M = segmenter_apply(self->seg, data1); carr_free(data1);
|
48
|
+
if (!M)
|
49
|
+
return NULL;
|
50
|
+
N = hamming_window_apply(self->ham, M); cmat_free(M);
|
51
|
+
M = power_spectrum_apply(self->pow, N); cmat_free(N);
|
52
|
+
N = mel_filter_apply(self->mel, M); cmat_free(M);
|
53
|
+
M = log_compressor_apply(self->log, N); cmat_free(N);
|
54
|
+
N = dct_apply(self->dct, M); cmat_free(M);
|
55
|
+
M = live_cmn_apply(self->cmn, N); cmat_free(N);
|
56
|
+
return M;
|
57
|
+
}
|