process.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /*
  2. * Squeezelite - lightweight headless squeezebox emulator
  3. *
  4. * (c) Adrian Smith 2012-2015, triode1@btinternet.com
  5. * Ralph Irving 2015-2017, ralph_irving@hotmail.com
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (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 General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. *
  20. */
  21. // sample processing - only included when building with PROCESS set
  22. #include "squeezelite.h"
  23. #if PROCESS
  24. extern log_level loglevel;
  25. extern struct buffer *outputbuf;
  26. extern struct decodestate decode;
  27. struct processstate process;
  28. extern struct codec *codec;
  29. #define LOCK_D mutex_lock(decode.mutex);
  30. #define UNLOCK_D mutex_unlock(decode.mutex);
  31. #define LOCK_O mutex_lock(outputbuf->mutex)
  32. #define UNLOCK_O mutex_unlock(outputbuf->mutex)
  33. // macros to map to processing functions - currently only resample.c
  34. // this can be made more generic when multiple processing mechanisms get added
  35. #if RESAMPLE || RESAMPLE16
  36. #define SAMPLES_FUNC resample_samples
  37. #define DRAIN_FUNC resample_drain
  38. #define NEWSTREAM_FUNC resample_newstream
  39. #define FLUSH_FUNC resample_flush
  40. #define INIT_FUNC resample_init
  41. #endif
  42. // transfer all processed frames to the output buf
  43. static void _write_samples(void) {
  44. frames_t frames = process.out_frames;
  45. ISAMPLE_T *iptr = (ISAMPLE_T *) process.outbuf;
  46. unsigned cnt = 10;
  47. LOCK_O;
  48. while (frames > 0) {
  49. frames_t f = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / BYTES_PER_FRAME;
  50. ISAMPLE_T *optr = (ISAMPLE_T*) outputbuf->writep;
  51. if (f > 0) {
  52. f = min(f, frames);
  53. memcpy(optr, iptr, f * BYTES_PER_FRAME);
  54. frames -= f;
  55. _buf_inc_writep(outputbuf, f * BYTES_PER_FRAME);
  56. iptr += f * BYTES_PER_FRAME / sizeof(*iptr);
  57. } else if (cnt--) {
  58. // there should normally be space in the output buffer, but may need to wait during drain phase
  59. UNLOCK_O;
  60. usleep(10000);
  61. LOCK_O;
  62. } else {
  63. // bail out if no space found after 100ms to avoid locking
  64. LOG_ERROR("unable to get space in output buffer");
  65. UNLOCK_O;
  66. return;
  67. }
  68. }
  69. UNLOCK_O;
  70. }
  71. // process samples - called with decode mutex set
  72. void process_samples(void) {
  73. SAMPLES_FUNC(&process);
  74. _write_samples();
  75. process.in_frames = 0;
  76. }
  77. // drain at end of track - called with decode mutex set
  78. void process_drain(void) {
  79. bool done;
  80. do {
  81. done = DRAIN_FUNC(&process);
  82. _write_samples();
  83. } while (!done);
  84. LOG_DEBUG("processing track complete - frames in: %lu out: %lu", process.total_in, process.total_out);
  85. }
  86. // new stream - called with decode mutex set
  87. unsigned process_newstream(bool *direct, unsigned raw_sample_rate, unsigned supported_rates[]) {
  88. bool active = NEWSTREAM_FUNC(&process, raw_sample_rate, supported_rates);
  89. LOG_INFO("processing: %s", active ? "active" : "inactive");
  90. *direct = !active;
  91. if (active) {
  92. unsigned max_in_frames, max_out_frames;
  93. process.in_frames = process.out_frames = 0;
  94. process.total_in = process.total_out = 0;
  95. max_in_frames = codec->min_space / BYTES_PER_FRAME ;
  96. // increase size of output buffer by 10% as output rate is not an exact multiple of input rate
  97. if (process.out_sample_rate % process.in_sample_rate == 0) {
  98. max_out_frames = max_in_frames * (process.out_sample_rate / process.in_sample_rate);
  99. } else {
  100. max_out_frames = (int)(1.1 * (float)max_in_frames * (float)process.out_sample_rate / (float)process.in_sample_rate);
  101. }
  102. if (process.max_in_frames != max_in_frames) {
  103. LOG_DEBUG("creating process buf in frames: %u", max_in_frames);
  104. if (process.inbuf) free(process.inbuf);
  105. process.inbuf = malloc(max_in_frames * BYTES_PER_FRAME);
  106. process.max_in_frames = max_in_frames;
  107. }
  108. if (process.max_out_frames != max_out_frames) {
  109. LOG_DEBUG("creating process buf out frames: %u", max_out_frames);
  110. if (process.outbuf) free(process.outbuf);
  111. process.outbuf = malloc(max_out_frames * BYTES_PER_FRAME);
  112. process.max_out_frames = max_out_frames;
  113. }
  114. if (!process.inbuf || !process.outbuf) {
  115. LOG_ERROR("malloc fail creating process buffers");
  116. *direct = true;
  117. return raw_sample_rate;
  118. }
  119. return process.out_sample_rate;
  120. }
  121. return raw_sample_rate;
  122. }
  123. // process flush - called with decode mutex set
  124. void process_flush(void) {
  125. LOG_INFO("process flush");
  126. FLUSH_FUNC();
  127. process.in_frames = 0;
  128. }
  129. // init - called with no mutex
  130. void process_init(char *opt) {
  131. bool enabled = INIT_FUNC(opt);
  132. memset(&process, 0, sizeof(process));
  133. if (enabled) {
  134. LOCK_D;
  135. decode.process = true;
  136. UNLOCK_D;
  137. }
  138. }
  139. #endif // #if PROCESS