-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlibkmaudio_interface.cpp
executable file
·169 lines (147 loc) · 3.92 KB
/
libkmaudio_interface.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#include "libkmaudio.h"
void getMax(int id, float fv);
void close_stream(int id)
{
#ifdef WIN32
if (devlist[id].capStream != NULL)
close_capture_stream(id);
if (devlist[id].pbStream != NULL)
close_playback_stream(id);
#else
if (devlist[id].instream != NULL)
close_capture_stream(id);
if (devlist[id].outstream != NULL)
close_playback_stream(id);
#endif
}
/*
* reads len samples from device id into psamp
* returns: number of values written to psamp , -1=error
* id ... device id returned by kmaudio_startCapture
* psamp ... float array of length len getting the audio data (mono)
* len ... number of float values to write into psamp
* volume ... 0.0f..2.0f will be multiplied with the input sample
* wait ... 1=wait for data, 0=return if not enough data available (in this case psamp will return 0,0,0...)
*
* if resampling is required the number of returned samples may differ from the number of requested samples
* it can be larger, so the buffer psamp should be larger than "len" by factor 1.1
*/
int kmaudio_readsamples(int id, float* psamp, int len, float volume, int wait)
{
int e = io_fifo_elems_avail(id);
if (e < len) return 0;
if (devlist[id].requested_samprate == devlist[id].real_samprate)
{
// data rate is ok, take samples as is
int nl = io_read_fifo_num(id, psamp, len);
for (int i = 0; i < nl; i++)
{
psamp[i] *= volume;
getMax(id, psamp[i]);
//kmaudio_detectDropouts(id);
}
return nl;
}
// resampling is required
int num = io_read_fifo_num(id, psamp, len);
if (num == 0) return 0;
int newlen = 0;
float *f = resample(id, psamp, len, &newlen);
for (int i = 0; i < newlen; i++)
{
psamp[i] = f[i] * volume;
getMax(id, psamp[i]);
}
return newlen;
}
/*
* plays len samples from psamp to device id
* returns: 0=ok, -1=error
* id ... device id returned by kmaudio_startPlayback
* psamp ... float array of length len with the audio data (mono)
* len ... number of float values in psamp
* volume ... 0.0f..2.0f will be multiplied with the output sample
*/
int kmaudio_playsamples(int id, float* psamp, int len, float volume)
{
// check if resampling is required
//printf("%d %d\n", devlist[id].requested_samprate , devlist[id].real_samprate);
if (devlist[id].requested_samprate == devlist[id].real_samprate)
{
// sampling rate is ok, just play samples
for (int i = 0; i < len; i++)
{
io_write_fifo(id, psamp[i] * volume);
getMax(id, psamp[i] * volume);
}
return 0;
}
// resampling is required
int newlen = 0;
float *f = resample(id, psamp, len, &newlen);
for (int i = 0; i < newlen; i++)
{
io_write_fifo(id, f[i] * volume);
getMax(id, f[i] * volume);
}
return 0;
}
#define MCHECK 48000 // abt. 1s of samples
float farr[MAXDEVICES][MCHECK];
int farridx[MAXDEVICES];
void init_maxarray()
{
// initialize arrays
for (int md = 0; md < MAXDEVICES; md++)
{
farridx[md] = 0;
for (int i = 0; i < MCHECK; i++)
farr[md][i] = 0;
}
}
void getMax(int id, float fv)
{
// put value into array
farr[id][farridx[id]] = fv;
if (++farridx[id] == MCHECK)
farridx[id] = 0;
}
/*
* returns the max level (within 1 second) of this stream in % (0..100)
* if the level >= 100 the signal will get clipped and distorted
*/
uint8_t kmaudio_maxlevel(int id)
{
float max = 0;
for (int i = 0; i < MCHECK; i++)
if (farr[id][i] > max) max = farr[id][i];
return (uint8_t)(max * 100);
}
void kmaudio_detectDropouts(int id)
{
int stat = 0;
int drlen = 0;
for (int i = 0; i < MCHECK; i++)
{
switch (stat)
{
case 0: // search beginning of dropout
if (farr[id][i] == 0.0f)
stat = 1;
break;
case 1: // count length of dropout
if (farr[id][i] == 0.0f) drlen++;
else
{
// end of dropout
if (drlen > 0)
{
printf("Dropout len:%d\n", drlen);
}
drlen = 0;
stat = 0;
}
break;
}
}
}