spkmodem-recv.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /* SPDX-License-Identifier: GPL-2.0-or-later */
  2. /* SPDX-FileCopyrightText: 2013 Free Software Foundation, Inc. */
  3. /* Usage: parec --channels=1 --rate=48000 --format=s16le | ./spkmodem-recv */
  4. /* Forked from coreboot's version, at util/spkmodem_recv/ in coreboot.git,
  5. * revision 5c2b5fcf2f9c9259938fd03cfa3ea06b36a007f0 as of 3 January 2022.
  6. * This version is heavily modified, re-written based on OpenBSD Kernel Source
  7. * File Style Guide (KNF); this change is Copyright 2023 Leah Rowe. */
  8. #include <err.h>
  9. #include <errno.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <unistd.h>
  14. #define SAMPLES_PER_FRAME 240
  15. #define MAX_SAMPLES (2 * SAMPLES_PER_FRAME)
  16. #define FREQ_SEP_MIN 5
  17. #define FREQ_SEP_MAX 15
  18. #define FREQ_DATA_MIN 15
  19. #define FREQ_DATA_THRESHOLD 25
  20. #define FREQ_DATA_MAX 60
  21. #define THRESHOLD 500
  22. #define ERR() (errno = errno ? errno : ECANCELED)
  23. #define reset_char() ascii = 0, ascii_bit = 7
  24. signed short frame[MAX_SAMPLES], pulse[MAX_SAMPLES];
  25. int ringpos, debug, freq_data, freq_separator, sample_count, ascii_bit = 7;
  26. char ascii = 0;
  27. void handle_audio(void);
  28. void decode_pulse(void);
  29. int set_ascii_bit(void);
  30. void print_char(void);
  31. void print_stats(void);
  32. int
  33. main(int argc, char *argv[])
  34. {
  35. int c;
  36. #ifdef __OpenBSD__
  37. if (pledge("stdio", NULL) == -1)
  38. err(ERR(), "pledge");
  39. #endif
  40. while ((c = getopt(argc, argv, "d")) != -1)
  41. if (!(debug = (c == 'd')))
  42. err(errno = EINVAL, NULL);
  43. setvbuf(stdout, NULL, _IONBF, 0);
  44. while (!feof(stdin))
  45. handle_audio();
  46. if (errno && debug)
  47. err(errno, "Unhandled error, errno %d", errno);
  48. return errno;
  49. }
  50. void
  51. handle_audio(void)
  52. {
  53. if (sample_count > (3 * SAMPLES_PER_FRAME))
  54. sample_count = reset_char();
  55. if ((freq_separator <= FREQ_SEP_MIN) || (freq_separator >= FREQ_SEP_MAX)
  56. || (freq_data <= FREQ_DATA_MIN) || (freq_data >= FREQ_DATA_MAX)) {
  57. decode_pulse();
  58. return;
  59. }
  60. if (set_ascii_bit() < 0)
  61. print_char();
  62. sample_count = 0;
  63. for (int sample = 0; sample < SAMPLES_PER_FRAME; sample++)
  64. decode_pulse();
  65. }
  66. void
  67. decode_pulse(void)
  68. {
  69. int next_ringpos = (ringpos + SAMPLES_PER_FRAME) % MAX_SAMPLES;
  70. freq_data -= pulse[ringpos];
  71. freq_data += pulse[next_ringpos];
  72. freq_separator -= pulse[next_ringpos];
  73. fread(frame + ringpos, 1, sizeof(frame[0]), stdin);
  74. if (ferror(stdin) != 0)
  75. err(ERR(), "Could not read from frame.");
  76. if ((pulse[ringpos] = (abs(frame[ringpos]) > THRESHOLD) ? 1 : 0))
  77. ++freq_separator;
  78. ++ringpos;
  79. ringpos %= MAX_SAMPLES;
  80. ++sample_count;
  81. }
  82. int
  83. set_ascii_bit(void)
  84. {
  85. if (debug)
  86. print_stats();
  87. if (freq_data < FREQ_DATA_THRESHOLD)
  88. ascii |= (1 << ascii_bit);
  89. --ascii_bit;
  90. return ascii_bit;
  91. }
  92. void
  93. print_char(void)
  94. {
  95. if (debug)
  96. printf("<%c, %x>", ascii, ascii);
  97. else
  98. printf("%c", ascii);
  99. reset_char();
  100. }
  101. void
  102. print_stats(void)
  103. {
  104. long stdin_pos;
  105. if ((stdin_pos = ftell(stdin)) == -1)
  106. err(ERR(), NULL);
  107. printf ("%d %d %d @%ld\n", freq_data, freq_separator,
  108. FREQ_DATA_THRESHOLD, stdin_pos - sizeof(frame));
  109. }