/***************************************************************** >file name : apps/common/sine_make.c >author : lichao >create time : Sun 05 May 2019 08:37:35 PM CST *****************************************************************/ #include "system/includes.h" #include "sine_make.h" #define SINE_USE_MALLOC 1 struct audio_sin_maker { u8 open; u8 id; u8 sin_num; u8 channel; u8 repeat; u8 next_param; u16 fade_points; /*int sample_rate;*/ int volume; int points; int sin_index; int win_sin_index; const struct sin_param *sin; }; #ifndef SINE_USE_MALLOC static struct audio_sin_maker sin_maker_handle; #endif void *sin_tone_open(const struct sin_param *param, int num, u8 channel, u8 repeat) { if (!param || !num) { return NULL; } #ifdef SINE_USE_MALLOC struct audio_sin_maker *sin = zalloc(sizeof(struct audio_sin_maker)); #else struct audio_sin_maker *sin = &sin_maker_handle; #endif if (!sin) { return NULL; } if (sin->open) { return NULL; } sin->sin = param; sin->sin_num = num; sin->open = 1; sin->points = param[0].points; sin->id = 0; sin->channel = channel; sin->repeat = repeat; #if (defined CONFIG_CPU_BR18 || \ CONFIG_CPU_BR21) /*这里如果加多fade points,会导致结束的时候有噪声,不是在淡出尾部*/ sin->fade_points = 0; #else sin->fade_points = 480; #endif sin->next_param = 1; return (void *)sin; } #if !defined(SINE_MAKE_IN_MASK) const int sf_sin_tab1[513] = { 0x00000000, 0x0000c910, 0x0001921f, 0x00025b2d, 0x0003243a, 0x0003ed45, 0x0004b64e, 0x00057f53, 0x00064855, 0x00071154, 0x0007da4e, 0x0008a343, 0x00096c33, 0x000a351d, 0x000afe00, 0x000bc6dd, 0x000c8fb3, 0x000d5881, 0x000e2147, 0x000eea03, 0x000fb2b7, 0x00107b61, 0x00114401, 0x00120c96, 0x0012d521, 0x00139d9f, 0x00146611, 0x00152e77, 0x0015f6d0, 0x0016bf1b, 0x00178758, 0x00184f87, 0x001917a7, 0x0019dfb7, 0x001aa7b7, 0x001b6fa7, 0x001c3786, 0x001cff53, 0x001dc70f, 0x001e8eb8, 0x001f564e, 0x00201dd1, 0x0020e541, 0x0021ac9b, 0x002273e2, 0x00233b13, 0x0024022e, 0x0024c933, 0x00259021, 0x002656f8, 0x00271db7, 0x0027e45f, 0x0028aaed, 0x00297163, 0x002a37bf, 0x002afe01, 0x002bc429, 0x002c8a35, 0x002d5026, 0x002e15fb, 0x002edbb4, 0x002fa14f, 0x003066ce, 0x00312c2e, 0x0031f170, 0x0032b694, 0x00337b98, 0x0034407c, 0x00350540, 0x0035c9e4, 0x00368e66, 0x003752c6, 0x00381705, 0x0038db21, 0x00399f19, 0x003a62ef, 0x003b26a0, 0x003bea2c, 0x003cad94, 0x003d70d7, 0x003e33f3, 0x003ef6e9, 0x003fb9b8, 0x00407c60, 0x00413ee0, 0x00420138, 0x0042c367, 0x0043856d, 0x0044474a, 0x004508fc, 0x0045ca83, 0x00468be0, 0x00474d11, 0x00480e16, 0x0048ceef, 0x00498f9a, 0x004a5019, 0x004b1069, 0x004bd08b, 0x004c907f, 0x004d5043, 0x004e0fd8, 0x004ecf3c, 0x004f8e70, 0x00504d72, 0x00510c43, 0x0051cae3, 0x0052894f, 0x00534789, 0x0054058f, 0x0054c362, 0x00558100, 0x00563e6a, 0x0056fb9e, 0x0057b89d, 0x00587565, 0x005931f7, 0x0059ee52, 0x005aaa76, 0x005b6662, 0x005c2215, 0x005cdd8f, 0x005d98d0, 0x005e53d8, 0x005f0ea5, 0x005fc937, 0x0060838f, 0x00613dab, 0x0061f78b, 0x0062b12e, 0x00636a95, 0x006423be, 0x0064dcaa, 0x00659557, 0x00664dc6, 0x006705f5, 0x0067bde5, 0x00687595, 0x00692d05, 0x0069e433, 0x006a9b21, 0x006b51cc, 0x006c0836, 0x006cbe5c, 0x006d7440, 0x006e29e0, 0x006edf3d, 0x006f9454, 0x00704927, 0x0070fdb5, 0x0071b1fd, 0x007265ff, 0x007319ba, 0x0073cd2f, 0x0074805c, 0x00753341, 0x0075e5dd, 0x00769831, 0x00774a3c, 0x0077fbfe, 0x0078ad75, 0x00795ea2, 0x007a0f84, 0x007ac01a, 0x007b7065, 0x007c2064, 0x007cd016, 0x007d7f7c, 0x007e2e93, 0x007edd5d, 0x007f8bd9, 0x00803a06, 0x0080e7e4, 0x00819573, 0x008242b1, 0x0082ef9f, 0x00839c3d, 0x00844889, 0x0084f484, 0x0085a02c, 0x00864b82, 0x0086f686, 0x0087a136, 0x00884b92, 0x0088f59b, 0x00899f4e, 0x008a48ad, 0x008af1b7, 0x008b9a6b, 0x008c42c9, 0x008cead0, 0x008d9281, 0x008e39da, 0x008ee0db, 0x008f8784, 0x00902dd5, 0x0090d3cd, 0x0091796b, 0x00921eb0, 0x0092c39a, 0x0093682a, 0x00940c5f, 0x0094b039, 0x009553b7, 0x0095f6d9, 0x0096999f, 0x00973c07, 0x0097de12, 0x00987fc0, 0x0099210f, 0x0099c200, 0x009a6293, 0x009b02c6, 0x009ba299, 0x009c420c, 0x009ce11f, 0x009d7fd1, 0x009e1e22, 0x009ebc12, 0x009f599f, 0x009ff6cb, 0x00a09393, 0x00a12ff9, 0x00a1cbfb, 0x00a26799, 0x00a302d3, 0x00a39da9, 0x00a4381a, 0x00a4d225, 0x00a56bcb, 0x00a6050a, 0x00a69de3, 0x00a73656, 0x00a7ce61, 0x00a86605, 0x00a8fd41, 0x00a99415, 0x00aa2a80, 0x00aac082, 0x00ab561b, 0x00abeb4a, 0x00ac800f, 0x00ad1469, 0x00ada859, 0x00ae3bde, 0x00aecef7, 0x00af61a5, 0x00aff3e6, 0x00b085bb, 0x00b11722, 0x00b1a81d, 0x00b238aa, 0x00b2c8c9, 0x00b3587a, 0x00b3e7bc, 0x00b4768f, 0x00b504f3, 0x00b592e7, 0x00b6206c, 0x00b6ad7f, 0x00b73a23, 0x00b7c655, 0x00b85216, 0x00b8dd65, 0x00b96842, 0x00b9f2ac, 0x00ba7ca4, 0x00bb0629, 0x00bb8f3b, 0x00bc17d9, 0x00bca003, 0x00bd27b8, 0x00bdaef9, 0x00be35c5, 0x00bebc1b, 0x00bf41fc, 0x00bfc767, 0x00c04c5c, 0x00c0d0da, 0x00c154e1, 0x00c1d870, 0x00c25b89, 0x00c2de29, 0x00c36051, 0x00c3e200, 0x00c46337, 0x00c4e3f5, 0x00c56439, 0x00c5e403, 0x00c66354, 0x00c6e22a, 0x00c76085, 0x00c7de65, 0x00c85bca, 0x00c8d8b3, 0x00c95521, 0x00c9d112, 0x00ca4c87, 0x00cac77f, 0x00cb41fa, 0x00cbbbf8, 0x00cc3578, 0x00ccae79, 0x00cd26fd, 0x00cd9f02, 0x00ce1689, 0x00ce8d90, 0x00cf0417, 0x00cf7a1f, 0x00cfefa8, 0x00d064af, 0x00d0d937, 0x00d14d3d, 0x00d1c0c2, 0x00d233c6, 0x00d2a649, 0x00d31849, 0x00d389c7, 0x00d3fac3, 0x00d46b3b, 0x00d4db31, 0x00d54aa4, 0x00d5b993, 0x00d627fe, 0x00d695e5, 0x00d70348, 0x00d77026, 0x00d7dc7f, 0x00d84853, 0x00d8b3a1, 0x00d91e6a, 0x00d988ad, 0x00d9f26a, 0x00da5ba0, 0x00dac450, 0x00db2c79, 0x00db941a, 0x00dbfb34, 0x00dc61c7, 0x00dcc7d1, 0x00dd2d53, 0x00dd924d, 0x00ddf6be, 0x00de5aa6, 0x00debe05, 0x00df20db, 0x00df8327, 0x00dfe4e9, 0x00e04621, 0x00e0a6cf, 0x00e106f2, 0x00e1668a, 0x00e1c598, 0x00e2241a, 0x00e28210, 0x00e2df7b, 0x00e33c5a, 0x00e398ac, 0x00e3f473, 0x00e44fac, 0x00e4aa59, 0x00e50479, 0x00e55e0b, 0x00e5b710, 0x00e60f88, 0x00e66771, 0x00e6becc, 0x00e71599, 0x00e76bd8, 0x00e7c187, 0x00e816a8, 0x00e86b39, 0x00e8bf3c, 0x00e912ae, 0x00e96591, 0x00e9b7e4, 0x00ea09a7, 0x00ea5ad9, 0x00eaab7b, 0x00eafb8c, 0x00eb4b0c, 0x00eb99fb, 0x00ebe858, 0x00ec3624, 0x00ec835e, 0x00ecd007, 0x00ed1c1d, 0x00ed67a1, 0x00edb293, 0x00edfcf2, 0x00ee46be, 0x00ee8ff8, 0x00eed89e, 0x00ef20b0, 0x00ef6830, 0x00efaf1b, 0x00eff573, 0x00f03b37, 0x00f08066, 0x00f0c501, 0x00f10908, 0x00f14c7a, 0x00f18f57, 0x00f1d19f, 0x00f21352, 0x00f25470, 0x00f294f8, 0x00f2d4eb, 0x00f31447, 0x00f3530e, 0x00f3913f, 0x00f3ced9, 0x00f40bdd, 0x00f4484b, 0x00f48422, 0x00f4bf62, 0x00f4fa0b, 0x00f5341d, 0x00f56d97, 0x00f5a67b, 0x00f5dec6, 0x00f6167a, 0x00f64d97, 0x00f6841b, 0x00f6ba07, 0x00f6ef5b, 0x00f72417, 0x00f7583a, 0x00f78bc5, 0x00f7beb7, 0x00f7f110, 0x00f822d1, 0x00f853f8, 0x00f88486, 0x00f8b47b, 0x00f8e3d6, 0x00f91298, 0x00f940c0, 0x00f96e4e, 0x00f99b43, 0x00f9c79d, 0x00f9f35e, 0x00fa1e84, 0x00fa4910, 0x00fa7302, 0x00fa9c59, 0x00fac516, 0x00faed37, 0x00fb14be, 0x00fb3bab, 0x00fb61fc, 0x00fb87b2, 0x00fbaccd, 0x00fbd14d, 0x00fbf531, 0x00fc187a, 0x00fc3b28, 0x00fc5d3a, 0x00fc7eb0, 0x00fc9f8a, 0x00fcbfc9, 0x00fcdf6c, 0x00fcfe73, 0x00fd1cdd, 0x00fd3aac, 0x00fd57de, 0x00fd7474, 0x00fd906e, 0x00fdabcc, 0x00fdc68c, 0x00fde0b1, 0x00fdfa38, 0x00fe1324, 0x00fe2b72, 0x00fe4323, 0x00fe5a38, 0x00fe70b0, 0x00fe868b, 0x00fe9bc9, 0x00feb069, 0x00fec46d, 0x00fed7d4, 0x00feea9d, 0x00fefcc9, 0x00ff0e58, 0x00ff1f49, 0x00ff2f9d, 0x00ff3f54, 0x00ff4e6d, 0x00ff5ce9, 0x00ff6ac7, 0x00ff7808, 0x00ff84ab, 0x00ff90b1, 0x00ff9c18, 0x00ffa6e3, 0x00ffb10f, 0x00ffba9e, 0x00ffc38f, 0x00ffcbe2, 0x00ffd397, 0x00ffdaaf, 0x00ffe129, 0x00ffe705, 0x00ffec43, 0x00fff0e3, 0x00fff4e6, 0x00fff84a, 0x00fffb11, 0x00fffd39, 0x00fffec4, 0x00ffffb1, 0x00ffffff, }; #else extern const int sf_sin_tab1[513] ; #endif #define SINE_INT_ZOOM 16384 #define SINE_INT_ZBIT 14 #define __int64 long long /*软件索引实现sin生成*/ static int get_sine_value(int mx_idx) { int ret = 0; int idx = 0; int tm_idx = mx_idx & 0x1FFFFFF; //2^25 int phase = tm_idx & 0x3FFF; int tp_idx0 = tm_idx >> 14; int tp_idx1 = tp_idx0 + 1; int sign = 1, dt0, dt1; if (tp_idx0 > 1024) { sign = -1; tp_idx0 = 2048 - tp_idx0; } if (tp_idx0 < 513) { dt0 = sf_sin_tab1[tp_idx0]; } else { dt0 = sf_sin_tab1[1024 - tp_idx0]; } if (tp_idx1 > 1024) { sign = -1; tp_idx1 = 2048 - tp_idx1; } if (tp_idx1 < 513) { dt1 = sf_sin_tab1[tp_idx1]; } else { dt1 = sf_sin_tab1[1024 - tp_idx1]; } ret = ((__int64)dt0 * (SINE_INT_ZOOM - phase) + (__int64)dt1 * phase) >> SINE_INT_ZBIT; ret *= sign; return ret; } static void hw_sin_value(int a, int *sin_res, u8 precision) { u64 s64 = a; *sin_res = __asm_sine(s64, precision); } int sin_tone_make(void *_maker, void *data, int len) { struct audio_sin_maker *maker = (struct audio_sin_maker *)_maker; s16 *pcm = (s16 *)data; int sin_value = 0; int win_sin_value = 0; int add_idx = 0, sub_vol = 0, win_add_idx = 0; int offset = 0; u8 id = maker->id; u8 sin_num = maker->sin_num; u8 repeat = maker->repeat; u8 channel = maker->channel; int sin_index; int win_sin_index; int volume; u32 reamin_points = len / 2 / channel; do { if (maker->next_param) { maker->volume = SINE_TOTAL_VOLUME; maker->sin_index = 0; maker->win_sin_index = 0; maker->next_param = 0; } u8 win = maker->sin[id].win; add_idx = ((u64)(1 << 25) * maker->sin[id].freq / DEFAULT_SINE_SAMPLE_RATE) >> 9; if (win) { win_add_idx = ((u64)(1 << 25) * maker->sin[id].decay / DEFAULT_SINE_SAMPLE_RATE) >> 9; /*sub_vol = 0;*/ } else { sub_vol = maker->sin[id].decay; } sin_index = maker->sin_index; win_sin_index = maker->win_sin_index; volume = maker->volume; u32 points = 0; if (maker->fade_points) { points = maker->fade_points > reamin_points ? reamin_points : maker->fade_points; sub_vol = 0; maker->fade_points -= points; } else { points = maker->points > reamin_points ? reamin_points : maker->points; maker->points -= points; } reamin_points -= points; while (points--) { /*hw_sin_value(sin_index, &sin_value, 0);*/ sin_value = __asm_sine((s64)sin_index, 2); if (win) { /*hw_sin_value(win_sin_index, &win_sin_value, 0);*/ win_sin_value = __asm_sine((s64)win_sin_index, 2); #ifdef CONFIG_CPU_BR36 sin_value = ((s64)sin_value * (s64)win_sin_value) >> 44; #else sin_value = ((s64)sin_value * (s64)win_sin_value) >> 34; #endif win_sin_index += win_add_idx; win_sin_index &= 0x1ffffff; } else { #ifdef CONFIG_CPU_BR36 sin_value = ((s64)volume * sin_value) >> 39; #else sin_value = ((s64)volume * sin_value) >> 34; #endif } sin_index += add_idx; sin_index &= 0x1ffffff; volume -= sub_vol; if (volume < 0) { volume = 0; } *pcm++ = sin_value; if (channel == 2) { *pcm++ = sin_value; } else if (channel == 4) { *pcm++ = sin_value; *pcm++ = sin_value; *pcm++ = sin_value; } } maker->volume = volume; maker->sin_index = sin_index; maker->win_sin_index = win_sin_index; if (!maker->points) { if (++id >= sin_num) { if (!repeat) { break; } id = 0; } maker->points = maker->sin[id].points; maker->id = id; maker->next_param = 1; } if (!reamin_points) { break; } } while (1); return len - (reamin_points * 2 * channel); } int sin_tone_points(void *_maker) { struct audio_sin_maker *maker = (struct audio_sin_maker *)_maker; int points = 0; u8 i = 0; for (i = 0; i < maker->sin_num; i++) { points += maker->sin[i].points; } return points; } void sin_tone_close(void *_maker) { struct audio_sin_maker *maker = (struct audio_sin_maker *)_maker; #ifdef SINE_USE_MALLOC if (maker) { free(maker); } #else if (sin_maker_handle.open) { sin_maker_handle.open = 0; } #endif }