-
Notifications
You must be signed in to change notification settings - Fork 35
Expand file tree
/
Copy pathCommonTools.h
More file actions
227 lines (206 loc) · 7.19 KB
/
CommonTools.h
File metadata and controls
227 lines (206 loc) · 7.19 KB
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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
#ifndef SONG_STUDIO_COMMON
#define SONG_STUDIO_COMMON
#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <sys/time.h>
#include <math.h>
#include <stdlib.h>
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define UINT64_C uint64_t
#define INT16_MAX 32767
#define INT16_MIN -32768
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
typedef signed short SInt16;
typedef unsigned char byte;
#define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
#define AUDIO_PCM_OUTPUT_CHANNEL 1
#define ACCOMPANY_PCM_OUTPUT_CHANNEL 2
static inline long long getCurrentTime()
{
struct timeval tv;
gettimeofday(&tv,NULL);
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
static inline long getCurrentTimeSecSinceReferenceDate()
{
struct timeval tv;
gettimeofday(&tv,NULL);
return tv.tv_sec;
}
inline int readShortFromFile(short *shortarray, int size, FILE* fp) {
int actualSize = fread(shortarray, 2, size, fp);
// LOGI("read data expected size is %d and size is %d", size, actualSize);
if (actualSize != size) {
// __android_log_print(ANDROID_LOG_INFO, "COMMON_TOOLS", "actualSize is %d size is %d", actualSize, size);
int flag = feof(fp);
if (flag != 0 && actualSize == 0) {
//到达文件末尾
// __android_log_print(ANDROID_LOG_INFO, "COMMON_TOOLS", "end of file, actualSize is %d", actualSize);
return -1;
}
}
return actualSize;
}
inline int readByteFromFile(byte *bytearray, int size, FILE* fp) {
int actualSize = fread(bytearray, 1, size, fp);
// LOGI("read data expected size is %d and size is %d", size, actualSize);
if (actualSize != size) {
int flag = feof(fp);
if (flag != 0 && actualSize == 0) {
//到达文件末尾
// LOGI("end of file");
return -1;
}
}
return actualSize;
}
//合并两个short,返回一个short
inline SInt16 TPMixSamples(SInt16 a, SInt16 b) {
int tmp = a < 0 && b < 0 ? ((int) a + (int) b) - (((int) a * (int) b) / INT16_MIN) : (a > 0 && b > 0 ? ((int) a + (int) b) - (((int) a * (int) b) / INT16_MAX) : a + b);
return tmp > INT16_MAX ? INT16_MAX : (tmp < INT16_MIN ? INT16_MIN : tmp);
}
//合并两个float,返回一个short
inline SInt16 TPMixSamplesFloat(float a, float b) {
int tmp = a < 0 && b < 0 ? ((int) a + (int) b) - (((int) a * (int) b) / INT16_MIN) : (a > 0 && b > 0 ? ((int) a + (int) b) - (((int) a * (int) b) / INT16_MAX) : a + b);
return tmp > INT16_MAX ? INT16_MAX : (tmp < INT16_MIN ? INT16_MIN : tmp);
}
//把一个short转换为一个长度为2的byte数组
inline void converttobytearray(SInt16 source, byte* bytes2) {
bytes2[0] = (byte) (source & 0xff);
bytes2[1] = (byte) ((source >> 8) & 0xff);
}
//将两个byte转换为一个short
inline SInt16 convertshort(byte* bytes) {
return (bytes[0] << 8) + (bytes[1] & 0xFF);
}
//调节音量的方法
inline SInt16 adjustAudioVolume(SInt16 source, float volume) {
/**
SInt16 result = source;
int temp = (int) ((int) source * volume);
if (temp < -0x8000) {
result = -0x8000;
} else if (temp > 0x7FFF) {
result = 0x7FFF;
} else {
result = (short) temp;
}
return result;
**/
SInt16 result = source;
int temp = (int) ((int) source * volume);
int sign = 1;
if (temp < 0) {
sign = -1;
}
int abstemp = abs(temp);
if (abstemp < 29490) {
result = temp;
}
else if (abstemp > 46285) {
result = 32767 * sign;
}
else if (abstemp > 32630) {
result = ((abstemp - 29490) / 8 + 30668)*sign;
}
else {
result = ((abstemp - 29490) / 2 + 29490)*sign;
}
return result;
}
//将一个short数组转换为一个byte数组---清唱时由于不需要和伴奏合成,所以直接转换;还有一个是当解码完成之后,需要将short变为byte数组,写入文件
inline void convertByteArrayFromShortArray(SInt16 *shortarray, int size, byte *bytearray) {
byte* tmpbytearray = new byte[2];
for (int i = 0; i < size; i++) {
converttobytearray(shortarray[i], tmpbytearray);
bytearray[i * 2] = tmpbytearray[0];
bytearray[i * 2 + 1] = tmpbytearray[1];
}
delete[] tmpbytearray;
}
//将一个byte数组转换为一个short数组---读进来audioRecord录制的pcm,然后将其从文件中读出字节流,然后在转换为short以方便后续处理
inline void convertShortArrayFromByteArray(byte *bytearray, int size, SInt16 *shortarray, float audioVolume) {
byte* bytes = new byte[2];
for (int i = 0; i < size / 2; i++) {
bytes[1] = bytearray[2 * i];
bytes[0] = bytearray[2 * i + 1];
SInt16 source = convertshort(bytes);
if (audioVolume != 1.0) {
shortarray[i] = adjustAudioVolume(source, audioVolume);
} else {
shortarray[i] = source;
}
}
delete[] bytes;
}
//客户端代码需要根据accompanySampleRate / audioSampleRate算出transfer_ratio;
//以及根据(int)((float)(sample_count) / accompanySampleRate * audioSampleRate)算出transfered_sample_count;
//并且分配出samples_transfered---将伴奏mp3解析成为pcm的short数组,需要先进行转换为录音的采样频率
inline void convertAccompanySampleRateByAudioSampleRate(SInt16 *samples, SInt16 *samples_transfered, int transfered_sample_count, float transfer_ratio) {
for (int i = 0; i < transfered_sample_count; i++) {
samples_transfered[i] = samples[(int) (i * transfer_ratio)];
}
}
//调节采样的音量---非清唱时候最终合成伴奏与录音的时候,判断如果accompanyVolume不是1.0的话,先调节伴奏的音量;而audioVolume是在读出的字节流转换为short流的时候调节的。
inline void adjustSamplesVolume(SInt16 *samples, int size, float accompanyVolume) {
if (accompanyVolume != 1.0) {
for (int i = 0; i < size; i++) {
samples[i] = adjustAudioVolume(samples[i], accompanyVolume);
}
}
}
//合成伴奏与录音,byte数组需要在客户端分配好内存---非清唱时候最终合成伴奏与录音调用
inline void mixtureAccompanyAudio(SInt16 *accompanyData, SInt16 *audioData, int size, byte *targetArray) {
byte* tmpbytearray = new byte[2];
for (int i = 0; i < size; i++) {
SInt16 audio = audioData[i];
SInt16 accompany = accompanyData[i];
SInt16 temp = TPMixSamples(accompany, audio);
converttobytearray(temp, tmpbytearray);
targetArray[i * 2] = tmpbytearray[0];
targetArray[i * 2 + 1] = tmpbytearray[1];
}
delete[] tmpbytearray;
}
//合成伴奏与录音,short数组需要在客户端分配好内存---非清唱时候边和边放调用
inline void mixtureAccompanyAudio(SInt16 *accompanyData, SInt16 *audioData, int size, short *targetArray) {
for (int i = 0; i < size; i++) {
SInt16 audio = audioData[i];
SInt16 accompany = accompanyData[i];
targetArray[i] = TPMixSamples(accompany, audio);
}
}
inline char *strstr(char *s1, char *s2) {
unsigned int i = 0;
if (*s1 == 0) // 如果字符串s1为空
{
if (*s2) // 如果字符串s2不为空
return (char*) NULL; // 则返回NULL
return (char*) s1; // 如果s2也为空,则返回s1
}
while (*s1) // 串s1没有结束
{
i = 0;
while (1) {
if (s2[i] == 0) {
return (char*) s1;
}
if (s2[i] != s1[i])
break;
i++;
}
s1++;
}
return (char*) NULL;
}
inline int strindex(char *s1, char *s2) {
int nPos = -1;
char *res = strstr(s1, s2);
if (res)
nPos = res - s1;
return nPos;
}
#endif //SONG_STUDIO_COMMON