outputbuffer.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. This file is part of QTau
  3. Copyright (C) 2013-2018 Tobias "Tomoko" Platen <tplaten@posteo.de>
  4. Copyright (C) 2013 digited <https://github.com/digited>
  5. Copyright (C) 2010-2013 HAL@ShurabaP <https://github.com/haruneko>
  6. QTau is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. SPDX-License-Identifier: GPL-3.0+
  17. */
  18. #include "audio/outputbuffer.h"
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <unistd.h>
  22. #include <stdint.h>
  23. #include <sys/time.h>
  24. #define __devloglevel__ 4
  25. #define debugperf 0
  26. #define debugperf2 0
  27. uint32_t getTime() {
  28. struct timeval tv;
  29. gettimeofday(&tv, NULL);
  30. uint32_t ret = static_cast<uint32_t>(tv.tv_usec / 1000 + tv.tv_sec * 1000);
  31. return ret;
  32. }
  33. OutputBuffer::OutputBuffer(JackAudio* jack) {
  34. _buffersize = 64 * 1024;
  35. _jackSamplerate = jack->getSamplerate();
  36. _ringbuffer = jack_ringbuffer_create(_buffersize);
  37. _sndfile = nullptr;
  38. _datacount = 0;
  39. start();
  40. }
  41. void OutputBuffer::scheduleSynth(ISynth* synth) {
  42. if (_scheduledSynth) return;
  43. _datacount = 0;
  44. _runtime = 0;
  45. jack_ringbuffer_reset(_ringbuffer);
  46. open("/tmp/test.wav", 44100);
  47. _scheduledSynth = synth;
  48. }
  49. void OutputBuffer::run() {
  50. int data_size = 1024 * 2;
  51. float* data = new float[data_size];
  52. uint32_t lasttime = getTime();
  53. while (1) {
  54. if (_scheduledSynth) {
  55. int end = _scheduledSynth->readData(data, data_size);
  56. if (end == 0) {
  57. _scheduledSynth->readData(nullptr, 0);
  58. _scheduledSynth = nullptr;
  59. close();
  60. continue;
  61. }
  62. int writespace = jack_ringbuffer_write_space(_ringbuffer);
  63. int size2 = data_size * sizeof(float);
  64. int sleepcount = 0;
  65. while (writespace < 2 * size2) {
  66. if (!_playbackIsStable) emit startPlayback();
  67. _playbackIsStable = true;
  68. usleep(1000);
  69. sleepcount++;
  70. writespace = jack_ringbuffer_write_space(_ringbuffer);
  71. }
  72. uint32_t currenttime = getTime();
  73. uint32_t timedelta = currenttime - lasttime;
  74. lasttime = currenttime;
  75. if (debugperf)
  76. DEVLOG_DEBUG("sleepcount " + STR(sleepcount) + " writespace " +
  77. STR(writespace) + " timedelta " + STR(timedelta));
  78. _runtime += timedelta;
  79. uint32_t timedelta_max = (int)(data_size * 1000 / 44100);
  80. if (debugperf2)
  81. if (timedelta > timedelta_max)
  82. DEVLOG_DEBUG("timedelta_max " + STR(timedelta_max) + " timedelta " +
  83. STR(timedelta - sleepcount));
  84. jack_ringbuffer_write(_ringbuffer, (char*)data, size2);
  85. sf_write_float(_sndfile, data, data_size);
  86. } else {
  87. usleep(20000); // nothing to do
  88. }
  89. }
  90. }
  91. // on synth start
  92. void OutputBuffer::open(QString fileName, int samplerate) {
  93. if (_sndfile) sf_close(_sndfile);
  94. SF_INFO info;
  95. memset(&info, 0, sizeof(info));
  96. info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
  97. info.samplerate = samplerate;
  98. info.channels = 1;
  99. _sndfile = sf_open(fileName.toUtf8().data(), SFM_WRITE, &info);
  100. if (_jackSamplerate != samplerate) {
  101. DEVLOG_ERROR("secret rabbit code is not implemented yet\n");
  102. }
  103. }
  104. void OutputBuffer::openReadFile(QString fileName) {
  105. SF_INFO info;
  106. memset(&info, 0, sizeof(info));
  107. _sndfile = sf_open(fileName.toUtf8().data(), SFM_READ, &info);
  108. _offline = true;
  109. }
  110. // on synth end
  111. void OutputBuffer::close() {
  112. if (_sndfile) sf_close(_sndfile);
  113. _sndfile = nullptr;
  114. jack_ringbuffer_reset(_ringbuffer);
  115. _datacount = 0;
  116. }
  117. // other thread -- copy engine
  118. void OutputBuffer::readData(float* data, int size) {
  119. if (_offline && _sndfile) {
  120. int count = sf_readf_float(_sndfile, data, size);
  121. if (count == 0) {
  122. DEVLOG_DEBUG("offline mode: stop playback");
  123. emit stopPlayback();
  124. close();
  125. }
  126. return;
  127. }
  128. // if(!_playbackIsStable) return; //do nothing
  129. unsigned int data_size = (unsigned int)size * sizeof(float);
  130. memset(data, 0, data_size);
  131. unsigned int readspace = jack_ringbuffer_read_space(_ringbuffer);
  132. float filled = readspace * 1.0 / _buffersize;
  133. if (filled < 0.5 && debugperf) DEVLOG_DEBUG("reading data " + STR(filled));
  134. if (!_playbackIsStable) return;
  135. if (readspace >= data_size) {
  136. jack_ringbuffer_read(_ringbuffer, (char*)data, data_size);
  137. } else {
  138. if (_scheduledSynth) {
  139. if (debugperf) DEVLOG_DEBUG("XRUN - cannot read from buffer");
  140. _xruncount++;
  141. } else {
  142. if (_playbackIsStable) {
  143. DEVLOG_DEBUG("end reached xruncount=" + STR(_xruncount) +
  144. " cputime=" + STR(_runtime));
  145. stopPlayback();
  146. _playbackIsStable = false;
  147. }
  148. }
  149. }
  150. }
  151. void OutputBuffer::reset() {
  152. jack_ringbuffer_reset(_ringbuffer);
  153. _datacount = 0;
  154. }