PageRenderTime 42ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/jni/Common.h

https://gitlab.com/madamovic-bg/FPlayAndroid
C Header | 542 lines | 427 code | 26 blank | 89 comment | 105 complexity | 6e6819be5075c4140045caf7a2eb57c5 MD5 | raw file
  1. //
  2. // FPlayAndroid is distributed under the FreeBSD License
  3. //
  4. // Copyright (c) 2013-2014, Carlos Rafael Gimenes das Neves
  5. // All rights reserved.
  6. //
  7. // Redistribution and use in source and binary forms, with or without
  8. // modification, are permitted provided that the following conditions are met:
  9. //
  10. // 1. Redistributions of source code must retain the above copyright notice, this
  11. // list of conditions and the following disclaimer.
  12. // 2. Redistributions in binary form must reproduce the above copyright notice,
  13. // this list of conditions and the following disclaimer in the documentation
  14. // and/or other materials provided with the distribution.
  15. //
  16. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  17. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  20. // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. //
  27. // The views and conclusions contained in the software and documentation are those
  28. // of the authors and should not be interpreted as representing official policies,
  29. // either expressed or implied, of the FreeBSD Project.
  30. //
  31. // https://github.com/carlosrafaelgn/FPlayAndroid
  32. //
  33. #include "SimpleMutex.h"
  34. #include "CommonNeon.h"
  35. #include "FixedFFT.h"
  36. #include <time.h>
  37. //for the alignment:
  38. //https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Variable-Attributes.html
  39. //to make the math easier COLORS has 257 int's (from 0 to 256) for each different color
  40. const unsigned short COLORS[] __attribute__((aligned(16))) = { /*Blue */ 0x0000, 0x0816, 0x0816, 0x0815, 0x0815, 0x0815, 0x1015, 0x1015, 0x1015, 0x1015, 0x1015, 0x1015, 0x1815, 0x1814, 0x1814, 0x1814, 0x1814, 0x2014, 0x2014, 0x2014, 0x2013, 0x2013, 0x2813, 0x2813, 0x2813, 0x2813, 0x3012, 0x3012, 0x3012, 0x3012, 0x3812, 0x3811, 0x3811, 0x3811, 0x4011, 0x4011, 0x4011, 0x4010, 0x4810, 0x4810, 0x4810, 0x4810, 0x500f, 0x500f, 0x500f, 0x500f, 0x580f, 0x580e, 0x580e, 0x600e, 0x600e, 0x600d, 0x680d, 0x680d, 0x680d, 0x680d, 0x700c, 0x700c, 0x700c, 0x780c, 0x780c, 0x780b, 0x800b, 0x800b, 0x800b, 0x800a, 0x880a, 0x880a, 0x880a, 0x900a, 0x9009, 0x9009, 0x9009, 0x9809, 0x9809, 0x9808, 0xa008, 0xa008, 0xa008, 0xa807, 0xa807, 0xa807, 0xa807, 0xb007, 0xb006, 0xb006, 0xb806, 0xb806, 0xb806, 0xb805, 0xc005, 0xc005, 0xc005, 0xc005, 0xc804, 0xc804, 0xc804, 0xc804, 0xd004, 0xd004, 0xd003, 0xd003, 0xd803, 0xd803, 0xd803, 0xd802, 0xe002, 0xe002, 0xe002, 0xe002, 0xe002, 0xe802, 0xe801, 0xe801, 0xe801, 0xe801, 0xf001, 0xf001, 0xf001, 0xf000, 0xf000, 0xf000, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf820, 0xf820, 0xf820, 0xf840, 0xf840, 0xf840, 0xf860, 0xf860, 0xf860, 0xf880, 0xf880, 0xf8a0, 0xf8a0, 0xf8a0, 0xf8c0, 0xf8c0, 0xf8e0, 0xf8e0, 0xf900, 0xf900, 0xf900, 0xf920, 0xf920, 0xf940, 0xf940, 0xf960, 0xf960, 0xf980, 0xf9a0, 0xf9a0, 0xf9a0, 0xf9c0, 0xf9e0, 0xf9e0, 0xfa00, 0xfa00, 0xfa20, 0xfa20, 0xfa40, 0xfa40, 0xfa60, 0xfa80, 0xfa80, 0xfaa0, 0xfaa0, 0xfac0, 0xfae0, 0xfae0, 0xfb00, 0xfb00, 0xfb20, 0xfb40, 0xfb40, 0xfb60, 0xfb60, 0xfb80, 0xfba0, 0xfba0, 0xfbc0, 0xfbe0, 0xfbe0, 0xfc00, 0xfc00, 0xfc20, 0xfc20, 0xfc40, 0xfc60, 0xfc60, 0xfc80, 0xfca0, 0xfca0, 0xfcc0, 0xfcc0, 0xfce0, 0xfd00, 0xfd00, 0xfd20, 0xfd20, 0xfd40, 0xfd60, 0xfd60, 0xfd80, 0xfd80, 0xfda0, 0xfda0, 0xfdc0, 0xfde0, 0xfde0, 0xfe00, 0xfe00, 0xfe20, 0xfe20, 0xfe40, 0xfe40, 0xfe60, 0xfe60, 0xfe80, 0xfe80, 0xfea0, 0xfea0, 0xfec0, 0xfec0, 0xfee0, 0xfee0, 0xff00, 0xff00, 0xff20, 0xff20, 0xff20, 0xff40, 0xff40, 0xff40, 0xff60, 0xff60, 0xff80, 0xff80, 0xff80, 0xffa0, 0xffa0, 0xffa0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0,
  41. /*Green*/ 0x0000, 0x0000, 0x0000, 0x0020, 0x0020, 0x0040, 0x0040, 0x0060, 0x0060, 0x0080, 0x00a0, 0x00a0, 0x00c0, 0x00e0, 0x00e0, 0x0100, 0x0120, 0x0140, 0x0160, 0x0160, 0x0180, 0x01a0, 0x01c0, 0x01e0, 0x01e0, 0x0200, 0x0220, 0x0240, 0x0260, 0x0280, 0x0280, 0x02a0, 0x02c0, 0x02e0, 0x0300, 0x0320, 0x0340, 0x0360, 0x0360, 0x0380, 0x03a0, 0x03c0, 0x03e0, 0x0400, 0x0400, 0x0420, 0x0440, 0x0440, 0x0460, 0x0480, 0x0480, 0x04a0, 0x04c0, 0x04c0, 0x04c0, 0x04e0, 0x04e0, 0x0ce0, 0x0d00, 0x0d00, 0x0d00, 0x1520, 0x1520, 0x1540, 0x1540, 0x1d40, 0x1d60, 0x1d60, 0x2580, 0x2580, 0x25a0, 0x2da0, 0x2da0, 0x2dc0, 0x35c0, 0x35e0, 0x35e0, 0x3e00, 0x3e00, 0x3e00, 0x4620, 0x4620, 0x4e40, 0x4e40, 0x4e60, 0x5660, 0x5660, 0x5e80, 0x5e80, 0x5ea0, 0x66a0, 0x66c0, 0x66c0, 0x6ec0, 0x6ee0, 0x76e0, 0x7700, 0x7f00, 0x7f00, 0x7f20, 0x8720, 0x8720, 0x8f40, 0x8f40, 0x8f40, 0x9760, 0x9760, 0x9f80, 0x9f80, 0x9f80, 0xa780, 0xa7a0, 0xafa0, 0xafa0, 0xafc0, 0xb7c0, 0xb7c0, 0xbfc0, 0xbfc0, 0xbfe0, 0xc7e0, 0xc7e0, 0xc7e0, 0xcfe0, 0xcfe0, 0xcfe0, 0xd7e0, 0xd7e0, 0xdfe0, 0xdfe0, 0xdfe0, 0xdfe0, 0xe7e0, 0xe7e0, 0xe7e0, 0xefe0, 0xefe0, 0xefe0, 0xefe0, 0xf7e0, 0xf7e0, 0xf7e0, 0xf7e0, 0xf7e0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffe0, 0xffc0, 0xffc0, 0xffc0, 0xffa0, 0xffa0, 0xffa0, 0xff80, 0xff80, 0xff80, 0xff60, 0xff60, 0xff40, 0xff40, 0xff40, 0xff20, 0xff00, 0xff00, 0xfee0, 0xfee0, 0xfec0, 0xfec0, 0xfea0, 0xfea0, 0xfe80, 0xfe60, 0xfe60, 0xfe40, 0xfe20, 0xfe20, 0xfe00, 0xfe00, 0xfde0, 0xfdc0, 0xfda0, 0xfda0, 0xfd80, 0xfd60, 0xfd60, 0xfd40, 0xfd20, 0xfd00, 0xfd00, 0xfce0, 0xfcc0, 0xfca0, 0xfca0, 0xfc80, 0xfc60, 0xfc40, 0xfc40, 0xfc20, 0xfc00, 0xfbe0, 0xfbe0, 0xfbc0, 0xfba0, 0xfb80, 0xfb60, 0xfb60, 0xfb40, 0xfb20, 0xfb00, 0xfb00, 0xfae0, 0xfac0, 0xfaa0, 0xfaa0, 0xfa80, 0xfa60, 0xfa60, 0xfa40, 0xfa20, 0xfa00, 0xfa00, 0xf9e0, 0xf9c0, 0xf9c0, 0xf9a0, 0xf980, 0xf980, 0xf960, 0xf960, 0xf940, 0xf920, 0xf920, 0xf900, 0xf8e0, 0xf8e0, 0xf8c0, 0xf8c0, 0xf8a0, 0xf8a0, 0xf880, 0xf880, 0xf860, 0xf860, 0xf860, 0xf840, 0xf840, 0xf820, 0xf820, 0xf820, 0xf800, 0xf800, 0xf800, 0xf800 };
  42. float floatBuffer[(256 * 2) + (256 / 4)] __attribute__((aligned(16)));
  43. float previousM[256] __attribute__((aligned(16)));
  44. float rootMeanSquare, lastRootMeanSquare;
  45. int vuMeter;
  46. #ifdef _MAY_HAVE_NEON_
  47. unsigned int neonMode, neonDone;
  48. int intBuffer[8] __attribute__((aligned(16)));
  49. #endif
  50. float commonCoefNew;
  51. unsigned int commonColorIndex, commonColorIndexApplied, commonTime, commonTimeLimit, commonLastTime;
  52. //Beat detection
  53. #define BEAT_STATE_VALLEY 0
  54. #define BEAT_STATE_PEAK 1
  55. #define BEAT_MIN_RISE_THRESHOLD 40
  56. unsigned int beatCounter, beatState, beatPeakOrValley, beatThreshold, beatDeltaMillis, beatSilenceDeltaMillis, beatSpeedBPM;
  57. float beatFilteredInput;
  58. unsigned int commonUptimeDeltaMillis(unsigned int* lastTime) {
  59. struct timespec t;
  60. t.tv_sec = 0;
  61. t.tv_nsec = 0;
  62. clock_gettime(CLOCK_MONOTONIC, &t);
  63. *((unsigned int*)&t) = (unsigned int)((((long)t.tv_sec) * 1000L) + (t.tv_nsec / 1000000L));
  64. const unsigned int delta = *((unsigned int*)&t) - *lastTime;
  65. *lastTime = *((unsigned int*)&t);
  66. return ((delta >= 100) ? 100 : delta);
  67. }
  68. void commonSRand() {
  69. struct timespec t;
  70. t.tv_sec = 0;
  71. t.tv_nsec = 0;
  72. clock_gettime(CLOCK_MONOTONIC, &t);
  73. srand((unsigned int)t.tv_nsec);
  74. }
  75. void JNICALL commonSetSpeed(JNIEnv* env, jclass clazz, int speed) {
  76. switch (speed) {
  77. case 1:
  78. commonCoefNew = COEF_SPEED_1;
  79. break;
  80. case 2:
  81. commonCoefNew = COEF_SPEED_2;
  82. break;
  83. default:
  84. commonCoefNew = COEF_SPEED_0;
  85. break;
  86. }
  87. }
  88. void JNICALL commonSetColorIndex(JNIEnv* env, jclass clazz, int jcolorIndex) {
  89. commonColorIndex = jcolorIndex;
  90. }
  91. int JNICALL commonCheckNeonMode(JNIEnv* env, jclass clazz) {
  92. #ifdef _MAY_HAVE_NEON_
  93. if (neonDone == 1)
  94. return neonMode;
  95. //based on
  96. //http://code.google.com/p/webrtc/source/browse/trunk/src/system_wrappers/source/android/cpu-features.c?r=2195
  97. //http://code.google.com/p/webrtc/source/browse/trunk/src/system_wrappers/source/android/cpu-features.h?r=2195
  98. neonMode = 0;
  99. char cpuinfo[4096];
  100. int cpuinfo_len = -1;
  101. int fd = open("/proc/cpuinfo", O_RDONLY);
  102. if (fd >= 0) {
  103. do {
  104. cpuinfo_len = read(fd, cpuinfo, 4096);
  105. } while (cpuinfo_len < 0 && errno == EINTR);
  106. close(fd);
  107. if (cpuinfo_len > 0) {
  108. cpuinfo[cpuinfo_len] = 0;
  109. //look for the "\nFeatures: " line
  110. for (int i = cpuinfo_len - 9; i >= 0; i--) {
  111. if (memcmp(cpuinfo + i, "\nFeatures", 9) == 0) {
  112. i += 9;
  113. while (i < cpuinfo_len && (cpuinfo[i] == ' ' || cpuinfo[i] == '\t' || cpuinfo[i] == ':'))
  114. i++;
  115. cpuinfo_len -= 5;
  116. //now look for the " neon" feature
  117. while (i <= cpuinfo_len && cpuinfo[i] != '\n') {
  118. if (memcmp(cpuinfo + i, " neon", 5) == 0 ||
  119. memcmp(cpuinfo + i, "\tneon", 5) == 0) {
  120. neonMode = 1;
  121. break;
  122. }
  123. i++;
  124. }
  125. break;
  126. }
  127. }
  128. // __android_log_print(ANDROID_LOG_INFO, "JNI", "Neon mode: %d", neonMode);
  129. }
  130. }
  131. neonDone = 1;
  132. return neonMode;
  133. #else
  134. return 0;
  135. #endif
  136. }
  137. void JNICALL commonUpdateMultiplier(JNIEnv* env, jclass clazz, jboolean isVoice) {
  138. float* const fft = floatBuffer;
  139. float* const multiplier = fft + 256;
  140. unsigned char* const processedData = (unsigned char*)(fft + 512);
  141. rootMeanSquare = 0;
  142. lastRootMeanSquare = 0;
  143. vuMeter = 0;
  144. beatCounter = 0;
  145. beatState = BEAT_STATE_VALLEY;
  146. beatPeakOrValley = 0;
  147. beatThreshold = BEAT_MIN_RISE_THRESHOLD;
  148. beatDeltaMillis = 0;
  149. beatSilenceDeltaMillis = 0;
  150. beatSpeedBPM = 0;
  151. beatFilteredInput = 0;
  152. if (isVoice) {
  153. for (int i = 0; i < 256; i++) {
  154. fft[i] = 0;
  155. processedData[i] = 0;
  156. previousM[i] = 0;
  157. //const double d = 180.0 - exp(1.0 / (((double)i / 10000.0) + 0.187));
  158. //multiplier[i] = ((d <= 1.5) ? 1.5f : (float)(d / 111.0));
  159. const double d = 5.0 * (400.0 - exp(1.0 / (((double)i / 3700.0) + 0.165)));
  160. multiplier[i] = ((d <= 256.0) ? 256.0f : (float)d) / 114.0f;
  161. //multiplier[i] = 2.0f * expf((float)i / 128.0f);
  162. }
  163. } else {
  164. for (int i = 0; i < 256; i++) {
  165. fft[i] = 0;
  166. processedData[i] = 0;
  167. previousM[i] = 0;
  168. //const double d = 180.0 - exp(1.0 / (((double)i / 10000.0) + 0.187));
  169. //multiplier[i] = ((d <= 1.5) ? 1.5f : (float)d);
  170. const double d = 5.0 * (400.0 - exp(1.0 / (((double)i / 3700.0) + 0.165)));
  171. multiplier[i] = ((d <= 256.0) ? 256.0f : (float)d);
  172. //multiplier[i] = 256.0f * expf((float)i / 128.0f);
  173. }
  174. }
  175. }
  176. int JNICALL commonProcess(JNIEnv* env, jclass clazz, jbyteArray jwaveform, int opt) {
  177. const unsigned int deltaMillis = commonUptimeDeltaMillis(&commonLastTime);
  178. beatDeltaMillis += deltaMillis;
  179. beatSilenceDeltaMillis += deltaMillis;
  180. int i;
  181. i = commonTime + deltaMillis;
  182. while (((unsigned int)i) >= commonTimeLimit)
  183. i -= commonTimeLimit;
  184. commonTime = i;
  185. //fft format:
  186. //index 0 1 2 3 4 5 ..... n-2 n-1
  187. // Rdc Rnyq R1 I1 R2 I2 R(n-1)/2 I(n-1)/2
  188. signed char* bfft;
  189. if (!(opt & IGNORE_INPUT) || (opt & BLUETOOTH_PROCESSING)) {
  190. bfft = (signed char*)env->GetPrimitiveArrayCritical(jwaveform, 0);
  191. if (!bfft)
  192. return 0;
  193. if (!(opt & IGNORE_INPUT)) {
  194. if ((opt & DATA_VUMETER))
  195. rootMeanSquare = sqrtf((float)doFft((unsigned char*)bfft, opt) * (1.0f / (float)(CAPTURE_SIZE)));
  196. else if ((opt & DATA_FFT))
  197. doFft((unsigned char*)bfft, DATA_FFT);
  198. //*** we are not drawing/analyzing the last bin (Nyquist) ;) ***
  199. bfft[1] = 0;
  200. }
  201. } else {
  202. bfft = 0;
  203. }
  204. vuMeter = 0;
  205. if ((opt & DATA_VUMETER)) {
  206. lastRootMeanSquare = ((rootMeanSquare > lastRootMeanSquare) ?
  207. (0.5f * rootMeanSquare) + ((1.0f - 0.5f) * lastRootMeanSquare)
  208. :
  209. (0.075f * rootMeanSquare) + ((1.0f - 0.075f) * lastRootMeanSquare));
  210. if (lastRootMeanSquare >= 1.0f) {
  211. const float v = 20.0f * log10f(lastRootMeanSquare / 42.0f);
  212. if (v > -20.0f) {
  213. vuMeter = (int)((v + 20.0f) * 12.75f);
  214. if (vuMeter > 255) vuMeter = 255;
  215. }
  216. }
  217. if (!(opt & ~(IGNORE_INPUT | DATA_VUMETER))) {
  218. if (bfft)
  219. env->ReleasePrimitiveArrayCritical(jwaveform, bfft, JNI_ABORT);
  220. return 0;
  221. }
  222. }
  223. unsigned char* processedData = (unsigned char*)(floatBuffer + 512);
  224. #ifdef _MAY_HAVE_NEON_
  225. if (!neonMode) {
  226. #endif
  227. float* fft = floatBuffer;
  228. const float* multiplier = floatBuffer + 256;
  229. const float coefNew = commonCoefNew * (float)deltaMillis;
  230. const float coefOld = 1.0f - coefNew;
  231. if ((opt & IGNORE_INPUT)) {
  232. for (i = 0; i < 256; i++) {
  233. float m = previousM[i];
  234. const float old = fft[i];
  235. if (m < old)
  236. m = (coefNew * m) + (coefOld * old);
  237. fft[i] = m;
  238. //v goes from 0 to 32768+ (inclusive)
  239. const unsigned int v = ((unsigned int)m) >> 7;
  240. processedData[i] = ((v >= 255) ? 255 : (unsigned char)v);
  241. }
  242. } else {
  243. for (i = 0; i < 256; i++) {
  244. //bfft[i] stores values from 0 to -128/127 (inclusive)
  245. const int re = (int)bfft[i << 1];
  246. const int im = (int)bfft[(i << 1) + 1];
  247. const int amplSq = (re * re) + (im * im);
  248. float m = ((amplSq < 8) ? 0.0f : (multiplier[i] * sqrtf((float)(amplSq))));
  249. previousM[i] = m;
  250. const float old = fft[i];
  251. if (m < old)
  252. m = (coefNew * m) + (coefOld * old);
  253. fft[i] = m;
  254. //v goes from 0 to 32768+ (inclusive)
  255. const unsigned int v = ((unsigned int)m) >> 7;
  256. processedData[i] = ((v >= 255) ? 255 : (unsigned char)v);
  257. }
  258. }
  259. #ifdef _MAY_HAVE_NEON_
  260. } else {
  261. commonProcessNeon(bfft, deltaMillis, opt);
  262. }
  263. #endif
  264. if ((opt & BEAT_DETECTION)) {
  265. //Beat detection (we are using a threshold of 25%)
  266. //processedData[0] = DC
  267. //processedData[1] = 1 * 44100/1024 = 43Hz
  268. //processedData[2] = 2 * 44100/1024 = 86Hz
  269. //processedData[3] = 3 * 44100/1024 = 129Hz
  270. //processedData[4] = 4 * 44100/1024 = 172Hz
  271. //processedData[5] = 5 * 44100/1024 = 215Hz
  272. //processedData[6] = 6 * 44100/1024 = 258Hz
  273. //processedData[7] = 7 * 44100/1024 = 301Hz
  274. //filter again
  275. beatFilteredInput = ((1.0f - 0.140625f) * beatFilteredInput) + (0.140625f * (float)processedData[(opt & BEAT_DETECTION) >> 12]);
  276. const unsigned int m = (unsigned int)beatFilteredInput;
  277. //__android_log_print(ANDROID_LOG_INFO, "JNI", "\t%d\t%d", (unsigned int)processedData[2], (unsigned int)processedData[3]);
  278. if (beatState == BEAT_STATE_VALLEY) {
  279. if (m < beatPeakOrValley) {
  280. //Just update the valley
  281. beatPeakOrValley = m;
  282. beatThreshold = ((m * 5) >> 2); //125%
  283. if (beatThreshold < BEAT_MIN_RISE_THRESHOLD)
  284. beatThreshold = BEAT_MIN_RISE_THRESHOLD;
  285. } else if (m >= beatThreshold && beatDeltaMillis >= 150) { //no more than 150 bpm
  286. //Check if we have crossed the threshold... Beat found! :D
  287. beatCounter++;
  288. //Average:
  289. //BPM = 60000 / beatDeltaMillis
  290. //BPM / 4 = 60000 / (4 * beatDeltaMillis)
  291. //BPM / 4 = 15000 / beatDeltaMillis
  292. //Since beatDeltaMillis accounts only for half of the period, we use 7500 instead of 15000
  293. //Let's not worry about division by 0 since beatDeltaMillis is incremented at the
  294. //beginning of this function (it would take 49 days and lot of concidence to reach 0!!!)
  295. beatSpeedBPM = ((beatSpeedBPM * 3) >> 2) + (7500 / beatDeltaMillis);
  296. //__android_log_print(ANDROID_LOG_INFO, "JNI", "%d %d", beatCounter >> 1, beatSpeedBPM);
  297. beatDeltaMillis = 0;
  298. beatSilenceDeltaMillis = 0;
  299. beatState = BEAT_STATE_PEAK;
  300. beatPeakOrValley = m;
  301. beatThreshold = ((m * 3) >> 2); //75%
  302. }
  303. } else {
  304. if (m > beatPeakOrValley) {
  305. //Just update the peak
  306. beatPeakOrValley = m;
  307. beatThreshold = ((m * 3) >> 2); //75%
  308. } else if (m <= beatThreshold && beatDeltaMillis >= 150) {
  309. //Check if we have crossed the threshold
  310. beatDeltaMillis = 0;
  311. beatState = BEAT_STATE_VALLEY;
  312. beatPeakOrValley = m;
  313. beatThreshold = ((m * 5) >> 2); //125%
  314. if (beatThreshold < BEAT_MIN_RISE_THRESHOLD)
  315. beatThreshold = BEAT_MIN_RISE_THRESHOLD;
  316. }
  317. }
  318. if (beatSilenceDeltaMillis >= 2000) {
  319. beatSpeedBPM = (beatSpeedBPM >> 1); //decrease the speed by 50% after 2s without beats
  320. beatSilenceDeltaMillis = 0;
  321. }
  322. }
  323. opt &= ~(IGNORE_INPUT | DATA_FFT | DATA_VUMETER | BEAT_DETECTION);
  324. if (!opt) {
  325. if (bfft)
  326. env->ReleasePrimitiveArrayCritical(jwaveform, bfft, JNI_ABORT);
  327. return 0;
  328. }
  329. //Bluetooth processing from here on
  330. #define PACK_BIN(BIN) if ((BIN) == 0x01 || (BIN) == 0x1B) { *packet = 0x1B; packet[1] = ((unsigned char)(BIN) ^ 1); packet += 2; len += 2; } else { *packet = (unsigned char)(BIN); packet++; len++; }
  331. #define MAX(A,B) (((A) > (B)) ? (A) : (B))
  332. unsigned char* packet = (unsigned char*)bfft;
  333. int len = 0, last;
  334. unsigned char avg;
  335. unsigned char b;
  336. packet[0] = 1; //SOH - Start of Heading
  337. packet[1] = (unsigned char)opt; //payload type
  338. //packet[2] and packet[3] are the payload length
  339. packet += 4;
  340. //PACK_BIN(beatCounter);
  341. //PACK_BIN(beatSpeedBPM);
  342. //PACK_BIN(vuMeter);
  343. //processedData stores the first 256 bins, out of the 512 captured by visualizer.getFft
  344. //which represents frequencies from DC to SampleRate / 4 (roughly from 0Hz to 11025Hz for a SR of 44100Hz)
  345. //
  346. //the mapping algorithms used in BLUETOOTH_BINS_4, BLUETOOTH_BINS_8, BLUETOOTH_BINS_16, BLUETOOTH_BINS_32,
  347. //BLUETOOTH_BINS_64 and in BLUETOOTH_BINS_128 were created empirically ;)
  348. switch (opt) {
  349. case BLUETOOTH_BINS_4:
  350. avg = MAX(processedData[0], processedData[1]);
  351. avg = MAX(avg, processedData[2]);
  352. avg = MAX(avg, processedData[3]);
  353. PACK_BIN(avg);
  354. i = 4;
  355. avg = processedData[i++];
  356. for (; i < 36; i++)
  357. avg = MAX(avg, processedData[i]);
  358. PACK_BIN(avg);
  359. avg = processedData[i++];
  360. for (; i < 100; i++)
  361. avg = MAX(avg, processedData[i]);
  362. PACK_BIN(avg);
  363. avg = processedData[i++];
  364. for (; i < 228; i++)
  365. avg = MAX(avg, processedData[i]);
  366. PACK_BIN(avg);
  367. break;
  368. case BLUETOOTH_BINS_8:
  369. avg = MAX(processedData[0], processedData[1]);
  370. PACK_BIN(avg);
  371. avg = MAX(processedData[2], processedData[3]);
  372. PACK_BIN(avg);
  373. i = 4;
  374. avg = processedData[i++];
  375. for (; i < 20; i++)
  376. avg = MAX(avg, processedData[i]);
  377. PACK_BIN(avg);
  378. avg = processedData[i++];
  379. for (; i < 36; i++)
  380. avg = MAX(avg, processedData[i]);
  381. PACK_BIN(avg);
  382. avg = processedData[i++];
  383. for (; i < 68; i++)
  384. avg = MAX(avg, processedData[i]);
  385. PACK_BIN(avg);
  386. avg = processedData[i++];
  387. for (; i < 100; i++)
  388. avg = MAX(avg, processedData[i]);
  389. PACK_BIN(avg);
  390. avg = processedData[i++];
  391. for (; i < 164; i++)
  392. avg = MAX(avg, processedData[i]);
  393. PACK_BIN(avg);
  394. avg = processedData[i++];
  395. for (; i < 228; i++)
  396. avg = MAX(avg, processedData[i]);
  397. PACK_BIN(avg);
  398. break;
  399. case BLUETOOTH_BINS_16:
  400. avg = MAX(processedData[0], processedData[1]);
  401. PACK_BIN(avg);
  402. avg = MAX(processedData[2], processedData[3]);
  403. PACK_BIN(avg);
  404. for (i = 4; i < 20; i += 4) {
  405. avg = MAX(processedData[i], processedData[i + 1]);
  406. avg = MAX(avg, processedData[i + 2]);
  407. avg = MAX(avg, processedData[i + 3]);
  408. PACK_BIN(avg);
  409. }
  410. for (last = 28; last <= 36; last += 8) {
  411. avg = processedData[i++];
  412. for (; i < last; i++)
  413. avg = MAX(avg, processedData[i]);
  414. PACK_BIN(avg);
  415. }
  416. for (last = 52; last <= 100; last += 16) {
  417. avg = processedData[i++];
  418. for (; i < last; i++)
  419. avg = MAX(avg, processedData[i]);
  420. PACK_BIN(avg);
  421. }
  422. for (last = 132; last <= 228; last += 32) {
  423. avg = processedData[i++];
  424. for (; i < last; i++)
  425. avg = MAX(avg, processedData[i]);
  426. PACK_BIN(avg);
  427. }
  428. break;
  429. case BLUETOOTH_BINS_32:
  430. b = processedData[0];
  431. PACK_BIN(b);
  432. b = processedData[1];
  433. PACK_BIN(b);
  434. b = processedData[2];
  435. PACK_BIN(b);
  436. b = processedData[3];
  437. PACK_BIN(b);
  438. for (i = 4; i < 20; i += 2) {
  439. avg = MAX(processedData[i], processedData[i + 1]);
  440. PACK_BIN(avg);
  441. }
  442. for (; i < 36; i += 4) {
  443. avg = MAX(processedData[i], processedData[i + 1]);
  444. avg = MAX(avg, processedData[i + 2]);
  445. avg = MAX(avg, processedData[i + 3]);
  446. PACK_BIN(avg);
  447. }
  448. for (last = 44; last <= 100; last += 8) {
  449. avg = processedData[i++];
  450. for (; i < last; i++)
  451. avg = MAX(avg, processedData[i]);
  452. PACK_BIN(avg);
  453. }
  454. for (last = 116; last <= 228; last += 16) {
  455. avg = processedData[i++];
  456. for (; i < last; i++)
  457. avg = MAX(avg, processedData[i]);
  458. PACK_BIN(avg);
  459. }
  460. break;
  461. case BLUETOOTH_BINS_64:
  462. for (i = 0; i < 20; i++) {
  463. b = processedData[i];
  464. PACK_BIN(b);
  465. }
  466. for (; i < 36; i += 2) {
  467. avg = MAX(processedData[i], processedData[i + 1]);
  468. PACK_BIN(avg);
  469. }
  470. for (; i < 132; i += 4) {
  471. avg = MAX(processedData[i], processedData[i + 1]);
  472. avg = MAX(avg, processedData[i + 2]);
  473. avg = MAX(avg, processedData[i + 3]);
  474. PACK_BIN(avg);
  475. }
  476. for (last = 140; last <= 228; last += 8) {
  477. avg = processedData[i++];
  478. for (; i < last; i++)
  479. avg = MAX(avg, processedData[i]);
  480. PACK_BIN(avg);
  481. }
  482. break;
  483. case BLUETOOTH_BINS_128:
  484. for (i = 0; i < 36; i++) {
  485. b = processedData[i];
  486. PACK_BIN(b);
  487. }
  488. for (; i < 184; i += 2) {
  489. avg = MAX(processedData[i], processedData[i + 1]);
  490. PACK_BIN(avg);
  491. }
  492. for (; i < 252; i += 4) {
  493. avg = MAX(processedData[i], processedData[i + 1]);
  494. avg = MAX(avg, processedData[i + 2]);
  495. avg = MAX(avg, processedData[i + 3]);
  496. PACK_BIN(avg);
  497. }
  498. break;
  499. case BLUETOOTH_BINS_256:
  500. for (i = 0; i < 256; i++) {
  501. b = processedData[i];
  502. PACK_BIN(b);
  503. }
  504. break;
  505. default:
  506. env->ReleasePrimitiveArrayCritical(jwaveform, bfft, JNI_ABORT);
  507. return 0;
  508. }
  509. #undef PACK_BIN
  510. //fill in the payload length
  511. ((unsigned char*)bfft)[2] = (len & 0x7F) << 1; //lower 7 bits, left shifted by 1
  512. ((unsigned char*)bfft)[3] = (len >> 6) & 0xFE; //upper 7 bits, left shifted by 1
  513. *packet = 4; //EOT - End of Transmission
  514. env->ReleasePrimitiveArrayCritical(jwaveform, bfft, 0);
  515. return len + 5;
  516. }