Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /*
  2. * Aptdec
  3. * Copyright (c) 2004 by Thierry Leconte (F4DWV)
  4. *
  5. * $Id$
  6. *
  7. * This library is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU Library General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Library General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Library General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. *
  21. */
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <math.h>
  26. #ifndef M_PI
  27. #define M_PI 3.1415926535 // For OS's that don't include it
  28. #endif
  29. #include "filter.h"
  30. #include "filtercoeff.h"
  31. /* WARNING
  32. * The comments in this file are at best educated guesses.
  33. * I am not a DSP god and can not figure out what a complicated
  34. * math function does just by looking at it.
  35. */
  36. extern int getsample(float *inbuff, int nb);
  37. #define BLKAMP 1024
  38. // Block size
  39. #define BLKIN 1024
  40. #define Fc 2400.0
  41. #define DFc 50.0
  42. #define PixelLine 2080
  43. #define Fp (2 * PixelLine)
  44. #define RSMULT 15
  45. #define Fi (Fp * RSMULT)
  46. static double Fe;
  47. static double offset = 0.0;
  48. static double FreqLine = 1.0;
  49. static double FreqOsc;
  50. static double K1, K2;
  51. // Check if the input sample rate is correct
  52. int init_dsp(double F) {
  53. if(F > Fi) return(1);
  54. if(F < Fp) return(-1);
  55. Fe = F;
  56. K1 = DFc / Fe;
  57. K2 = K1 * K1 / 2.0;
  58. FreqOsc = Fc / Fe;
  59. return(0);
  60. }
  61. // Fast phase estimator
  62. // Calculates the phase angle of a signal from a IQ sample
  63. static inline double Phase(double I, double Q) {
  64. double angle, r;
  65. int s;
  66. if(I == 0.0 && Q == 0.0)
  67. return(0.0);
  68. if (Q < 0) {
  69. s = -1;
  70. Q = -Q;
  71. } else {
  72. s = 1;
  73. }
  74. if (I >= 0) {
  75. r = (I - Q) / (I + Q);
  76. angle = 0.25 - 0.25 * r;
  77. } else {
  78. r = (I + Q) / (Q - I);
  79. angle = 0.75 - 0.25 * r;
  80. }
  81. if(s > 0)
  82. return(angle);
  83. else
  84. return(-angle);
  85. }
  86. // Phase locked loop
  87. // Used to get value from an IQ sample with noise reduction
  88. static double pll(double I, double Q) {
  89. // PLL coefficient
  90. static double PhaseOsc = 0.0;
  91. double Io, Qo;
  92. double Ip, Qp;
  93. double DPhi;
  94. // Quadrature oscillator / reference
  95. Io = cos(PhaseOsc);
  96. Qo = sin(PhaseOsc);
  97. // Phase detector
  98. Ip = I * Io + Q * Qo;
  99. Qp = Q * Io - I * Qo;
  100. DPhi = Phase(Ip, Qp);
  101. // Loop filter
  102. PhaseOsc += 2.0 * M_PI * (K1 * DPhi + FreqOsc);
  103. if (PhaseOsc > M_PI)
  104. PhaseOsc -= 2.0 * M_PI;
  105. if (PhaseOsc <= -M_PI)
  106. PhaseOsc += 2.0 * M_PI;
  107. FreqOsc += K2 * DPhi;
  108. if (FreqOsc > ((Fc + DFc) / Fe))
  109. FreqOsc = (Fc + DFc) / Fe;
  110. if (FreqOsc < ((Fc - DFc) / Fe))
  111. FreqOsc = (Fc - DFc) / Fe;
  112. return(Ip);
  113. }
  114. // Convert audio samples into a pixel
  115. static int getamp(double *ambuff, int nb) {
  116. static float inbuff[BLKIN];
  117. static int idxin = 0;
  118. static int nin = 0;
  119. int n;
  120. for (n = 0; n < nb; n++) {
  121. double I, Q;
  122. // If the amount of samples is small enough to be processed
  123. if (nin < IQFilterLen * 2 + 2) {
  124. // Number of samples read
  125. int res;
  126. memmove(inbuff, &(inbuff[idxin]), nin * sizeof(float));
  127. idxin = 0;
  128. // Read some samples
  129. res = getsample(&(inbuff[nin]), BLKIN - nin);
  130. nin += res;
  131. // If we haven't read any more samples, return how far we got
  132. if (nin < IQFilterLen * 2 + 2)
  133. return(n);
  134. }
  135. // Process read samples into a brightness value
  136. iqfir(&inbuff[idxin], iqfilter, IQFilterLen, &I, &Q);
  137. ambuff[n] = pll(I, Q);
  138. idxin += 1;
  139. nin -= 1;
  140. }
  141. return(n);
  142. }
  143. // Get an entire row of pixels, without alignment
  144. int getpixelv(float *pvbuff, int nb) {
  145. // Amplitude buffer
  146. static double ambuff[BLKAMP];
  147. static int nam = 0;
  148. static int idxam = 0;
  149. int n, m;
  150. double mult;
  151. mult = (double) Fi / Fe * FreqLine;
  152. m = RSFilterLen / mult + 1;
  153. for (n = 0; n < nb; n++) {
  154. int shift;
  155. if (nam < m) {
  156. int res;
  157. memmove(ambuff, &(ambuff[idxam]), nam * sizeof(double));
  158. idxam = 0;
  159. res = getamp(&(ambuff[nam]), BLKAMP - nam);
  160. nam += res;
  161. if (nam < m)
  162. return(n);
  163. }
  164. // Denoise
  165. pvbuff[n] = rsfir(&(ambuff[idxam]), rsfilter, RSFilterLen, offset, mult) * mult * 256.0;
  166. shift = ((int) floor((RSMULT - offset) / mult)) + 1;
  167. offset = shift * mult + offset - RSMULT;
  168. idxam += shift;
  169. nam -= shift;
  170. }
  171. return(nb);
  172. }
  173. // Align this line based off of the synchronisation markers
  174. int getpixelrow(float *pixelv) {
  175. // Create an array for this row
  176. static float pixels[PixelLine + SyncFilterLen];
  177. static int npv = 0;
  178. static int synced = 0;
  179. static double max = 0.0;
  180. double corr, ecorr, lcorr;
  181. int res;
  182. if (npv > 0)
  183. memmove(pixelv, pixels, npv * sizeof(float));
  184. if (npv < SyncFilterLen + 2) {
  185. res = getpixelv(&(pixelv[npv]), SyncFilterLen + 2 - npv);
  186. npv += res;
  187. if (npv < SyncFilterLen + 2)
  188. return(0);
  189. }
  190. // Test current synchronisation
  191. ecorr = fir(pixelv, Sync, SyncFilterLen);
  192. corr = fir(&(pixelv[1]), Sync, SyncFilterLen - 1);
  193. lcorr = fir(&(pixelv[2]), Sync, SyncFilterLen - 2);
  194. // Calculate the per pixel offset
  195. FreqLine = 1.0+((ecorr-lcorr) / corr / PixelLine / 4.0);
  196. // Maximum acceptable offset
  197. if (corr < 0.75 * max) {
  198. synced = 0;
  199. FreqLine = 1.0;
  200. }
  201. max = corr;
  202. if (synced < 8) {
  203. int mshift;
  204. if (npv < PixelLine + SyncFilterLen) {
  205. res = getpixelv(&(pixelv[npv]), PixelLine + SyncFilterLen - npv);
  206. npv += res;
  207. if (npv < PixelLine + SyncFilterLen)
  208. return(0);
  209. }
  210. // Shift this line until we see the best results
  211. mshift = 0;
  212. for (int shift = 1; shift < PixelLine; shift++) {
  213. double corr;
  214. corr = fir(&(pixelv[shift + 1]), Sync, SyncFilterLen);
  215. if (corr > max) {
  216. mshift = shift;
  217. max = corr;
  218. }
  219. }
  220. // Shift memory, shifting this row
  221. if (mshift != 0) {
  222. memmove(pixelv, &(pixelv[mshift]), (npv - mshift) * sizeof(float));
  223. npv -= mshift;
  224. synced = 0;
  225. FreqLine = 1.0;
  226. } else
  227. synced += 1;
  228. }
  229. // If there are not enough pixels try to grab some more
  230. if (npv < PixelLine) {
  231. res = getpixelv(&(pixelv[npv]), PixelLine - npv);
  232. npv += res;
  233. // If we fail this then exit with 0 (which breaks the loop at main.c:338)
  234. if (npv < PixelLine)
  235. return(0);
  236. }
  237. // If we're finished reset npv to 0
  238. if (npv == PixelLine) {
  239. npv = 0;
  240. } else { // Move the pixel build buffer to the output buffer
  241. memmove(pixels, &(pixelv[PixelLine]), (npv - PixelLine) * sizeof(float));
  242. npv -= PixelLine;
  243. }
  244. return(1);
  245. }