jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

493 lines
15KB

  1. /*
  2. Copyright (C) 2023 Florian Walpen <dev@submerge.ch>
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include "JackOSSChannel.h"
  16. #include "JackError.h"
  17. #include "JackThread.h"
  18. #include "memops.h"
  19. #include <cstdint>
  20. #include <sys/ioctl.h>
  21. #include <sys/soundcard.h>
  22. #include <fcntl.h>
  23. #include <iostream>
  24. #include <assert.h>
  25. #include <stdio.h>
  26. typedef jack_default_audio_sample_t jack_sample_t;
  27. namespace
  28. {
  29. int SuggestSampleFormat(int bits)
  30. {
  31. switch(bits) {
  32. // Native-endian signed 32 bit samples.
  33. case 32:
  34. return AFMT_S32_NE;
  35. // Native-endian signed 24 bit (packed) samples.
  36. case 24:
  37. return AFMT_S24_NE;
  38. // Native-endian signed 16 bit samples, used by default.
  39. case 16:
  40. default:
  41. return AFMT_S16_NE;
  42. }
  43. }
  44. bool SupportedSampleFormat(int format)
  45. {
  46. switch(format) {
  47. // Only signed sample formats are supported by the conversion functions.
  48. case AFMT_S16_NE:
  49. case AFMT_S16_OE:
  50. case AFMT_S24_NE:
  51. case AFMT_S24_OE:
  52. case AFMT_S32_NE:
  53. case AFMT_S32_OE:
  54. return true;
  55. }
  56. return false;
  57. }
  58. void CopyAndConvertIn(jack_sample_t *dst, char *src, size_t nframes, int channel, int chcount, int format)
  59. {
  60. switch (format) {
  61. case AFMT_S16_NE:
  62. src += channel * 2;
  63. sample_move_dS_s16(dst, src, nframes, chcount * 2);
  64. break;
  65. case AFMT_S16_OE:
  66. src += channel * 2;
  67. sample_move_dS_s16s(dst, src, nframes, chcount * 2);
  68. break;
  69. case AFMT_S24_NE:
  70. src += channel * 3;
  71. sample_move_dS_s24(dst, src, nframes, chcount * 3);
  72. break;
  73. case AFMT_S24_OE:
  74. src += channel * 3;
  75. sample_move_dS_s24s(dst, src, nframes, chcount * 3);
  76. break;
  77. case AFMT_S32_NE:
  78. src += channel * 4;
  79. sample_move_dS_s32(dst, src, nframes, chcount * 4);
  80. break;
  81. case AFMT_S32_OE:
  82. src += channel * 4;
  83. sample_move_dS_s32s(dst, src, nframes, chcount * 4);
  84. break;
  85. }
  86. }
  87. void CopyAndConvertOut(char *dst, jack_sample_t *src, size_t nframes, int channel, int chcount, int format)
  88. {
  89. switch (format) {
  90. case AFMT_S16_NE:
  91. dst += channel * 2;
  92. sample_move_d16_sS(dst, src, nframes, chcount * 2, NULL);
  93. break;
  94. case AFMT_S16_OE:
  95. dst += channel * 2;
  96. sample_move_d16_sSs(dst, src, nframes, chcount * 2, NULL);
  97. break;
  98. case AFMT_S24_NE:
  99. dst += channel * 3;
  100. sample_move_d24_sS(dst, src, nframes, chcount * 3, NULL);
  101. break;
  102. case AFMT_S24_OE:
  103. dst += channel * 3;
  104. sample_move_d24_sSs(dst, src, nframes, chcount * 3, NULL);
  105. break;
  106. case AFMT_S32_NE:
  107. dst += channel * 4;
  108. sample_move_d32_sS(dst, src, nframes, chcount * 4, NULL);
  109. break;
  110. case AFMT_S32_OE:
  111. dst += channel * 4;
  112. sample_move_d32_sSs(dst, src, nframes, chcount * 4, NULL);
  113. break;
  114. }
  115. }
  116. }
  117. void sosso::Log::log(sosso::SourceLocation location, const char* message) {
  118. jack_log(message);
  119. }
  120. void sosso::Log::info(sosso::SourceLocation location, const char* message) {
  121. jack_info(message);
  122. }
  123. void sosso::Log::warn(sosso::SourceLocation location, const char* message) {
  124. jack_error(message);
  125. }
  126. namespace Jack
  127. {
  128. bool JackOSSChannel::InitialSetup(unsigned int sample_rate)
  129. {
  130. fFrameStamp = 0;
  131. fCorrection.clear();
  132. return fFrameClock.set_sample_rate(sample_rate);
  133. }
  134. bool JackOSSChannel::OpenCapture(const char *device, bool exclusive, int bits, int &channels)
  135. {
  136. if (channels == 0) channels = 2;
  137. int sample_format = SuggestSampleFormat(bits);
  138. if (!fReadChannel.set_parameters(sample_format, fFrameClock.sample_rate(), channels)) {
  139. jack_error("JackOSSChannel::OpenCapture unsupported sample format %#x", sample_format);
  140. return false;
  141. }
  142. if (!fReadChannel.open(device, exclusive)) {
  143. return false;
  144. }
  145. if (fReadChannel.sample_rate() != fFrameClock.sample_rate()) {
  146. jack_error("JackOSSChannel::OpenCapture driver forced sample rate %ld", fReadChannel.sample_rate());
  147. fReadChannel.close();
  148. return false;
  149. }
  150. if (!SupportedSampleFormat(fReadChannel.sample_format())) {
  151. jack_error("JackOSSChannel::OpenCapture unsupported sample format %#x", fReadChannel.sample_format());
  152. fReadChannel.close();
  153. return false;
  154. }
  155. jack_log("JackOSSChannel::OpenCapture capture file descriptor = %d", fReadChannel.file_descriptor());
  156. if (fReadChannel.channels() != channels) {
  157. channels = fReadChannel.channels();
  158. jack_info("JackOSSChannel::OpenCapture driver forced the number of capture channels %ld", channels);
  159. }
  160. fReadChannel.memory_map();
  161. return true;
  162. }
  163. bool JackOSSChannel::OpenPlayback(const char *device, bool exclusive, int bits, int &channels)
  164. {
  165. if (channels == 0) channels = 2;
  166. int sample_format = SuggestSampleFormat(bits);
  167. if (!fWriteChannel.set_parameters(sample_format, fFrameClock.sample_rate(), channels)) {
  168. jack_error("JackOSSChannel::OpenPlayback unsupported sample format %#x", sample_format);
  169. return false;
  170. }
  171. if (!fWriteChannel.open(device, exclusive)) {
  172. return false;
  173. }
  174. if (fWriteChannel.sample_rate() != fFrameClock.sample_rate()) {
  175. jack_error("JackOSSChannel::OpenPlayback driver forced sample rate %ld", fWriteChannel.sample_rate());
  176. fWriteChannel.close();
  177. return false;
  178. }
  179. if (!SupportedSampleFormat(fWriteChannel.sample_format())) {
  180. jack_error("JackOSSChannel::OpenPlayback unsupported sample format %#x", fWriteChannel.sample_format());
  181. fWriteChannel.close();
  182. return false;
  183. }
  184. jack_log("JackOSSChannel::OpenPlayback playback file descriptor = %d", fWriteChannel.file_descriptor());
  185. if (fWriteChannel.channels() != channels) {
  186. channels = fWriteChannel.channels();
  187. jack_info("JackOSSChannel::OpenPlayback driver forced the number of playback channels %ld", channels);
  188. }
  189. fWriteChannel.memory_map();
  190. return true;
  191. }
  192. bool JackOSSChannel::Read(jack_sample_t **sample_buffers, jack_nframes_t length, std::int64_t end)
  193. {
  194. if (fReadChannel.recording()) {
  195. // Get buffer from read channel.
  196. sosso::Buffer buffer = fReadChannel.take_buffer();
  197. // Get recording audio data and then clear buffer.
  198. for (unsigned i = 0; i < fReadChannel.channels(); i++) {
  199. if (sample_buffers[i]) {
  200. CopyAndConvertIn(sample_buffers[i], buffer.data(), length, i, fReadChannel.channels(), fReadChannel.sample_format());
  201. }
  202. }
  203. buffer.reset();
  204. // Put buffer back to capture at requested end position.
  205. fReadChannel.set_buffer(std::move(buffer), end);
  206. SignalWork();
  207. return true;
  208. }
  209. return false;
  210. }
  211. bool JackOSSChannel::Write(jack_sample_t **sample_buffers, jack_nframes_t length, std::int64_t end)
  212. {
  213. if (fWriteChannel.playback()) {
  214. // Get buffer from write channel.
  215. sosso::Buffer buffer = fWriteChannel.take_buffer();
  216. // Clear buffer and write new playback audio data.
  217. memset(buffer.data(), 0, buffer.length());
  218. buffer.reset();
  219. for (unsigned i = 0; i < fWriteChannel.channels(); i++) {
  220. if (sample_buffers[i]) {
  221. CopyAndConvertOut(buffer.data(), sample_buffers[i], length, i, fWriteChannel.channels(), fWriteChannel.sample_format());
  222. }
  223. }
  224. // Put buffer back to playback at requested end position.
  225. end += PlaybackCorrection();
  226. fWriteChannel.set_buffer(std::move(buffer), end);
  227. SignalWork();
  228. return true;
  229. }
  230. return false;
  231. }
  232. bool JackOSSChannel::StartChannels(unsigned int buffer_frames)
  233. {
  234. int group_id = 0;
  235. if (fReadChannel.recording()) {
  236. // Allocate two recording buffers for double buffering.
  237. size_t buffer_size = buffer_frames * fReadChannel.frame_size();
  238. sosso::Buffer buffer((char*) calloc(buffer_size, 1), buffer_size);
  239. assert(buffer.data());
  240. fReadChannel.set_buffer(std::move(buffer), 0);
  241. buffer = sosso::Buffer((char*) calloc(buffer_size, 1), buffer_size);
  242. assert(buffer.data());
  243. fReadChannel.set_buffer(std::move(buffer), buffer_frames);
  244. // Add recording channel to synced start group.
  245. fReadChannel.add_to_sync_group(group_id);
  246. }
  247. if (fWriteChannel.playback()) {
  248. // Allocate two playback buffers for double buffering.
  249. size_t buffer_size = buffer_frames * fWriteChannel.frame_size();
  250. sosso::Buffer buffer((char*) calloc(buffer_size, 1), buffer_size);
  251. assert(buffer.data());
  252. fWriteChannel.set_buffer(std::move(buffer), 0);
  253. buffer = sosso::Buffer((char*) calloc(buffer_size, 1), buffer_size);
  254. assert(buffer.data());
  255. fWriteChannel.set_buffer(std::move(buffer), buffer_frames);
  256. // Add playback channel to synced start group.
  257. fWriteChannel.add_to_sync_group(group_id);
  258. }
  259. // Start both channels in sync if supported.
  260. if (fReadChannel.recording()) {
  261. fReadChannel.start_sync_group(group_id);
  262. } else {
  263. fWriteChannel.start_sync_group(group_id);
  264. }
  265. // Init frame clock here to mark start time.
  266. if (!fFrameClock.init_clock(fFrameClock.sample_rate())) {
  267. return false;
  268. }
  269. // Small drift corrections to keep latency whithin +/- 1ms.
  270. std::int64_t limit = fFrameClock.sample_rate() / 1000;
  271. fCorrection.set_drift_limits(-limit, limit);
  272. // Drastic corrections when drift exceeds half a period.
  273. limit = std::max<std::int64_t>(limit, buffer_frames / 2);
  274. fCorrection.set_loss_limits(-limit, limit);
  275. SignalWork();
  276. return true;
  277. }
  278. bool JackOSSChannel::StopChannels()
  279. {
  280. if (fReadChannel.recording()) {
  281. free(fReadChannel.take_buffer().data());
  282. free(fReadChannel.take_buffer().data());
  283. fReadChannel.memory_unmap();
  284. fReadChannel.close();
  285. }
  286. if (fWriteChannel.playback()) {
  287. free(fWriteChannel.take_buffer().data());
  288. free(fWriteChannel.take_buffer().data());
  289. fWriteChannel.memory_unmap();
  290. fWriteChannel.close();
  291. }
  292. return true;
  293. }
  294. bool JackOSSChannel::StartAssistThread(bool realtime, int priority)
  295. {
  296. if (fAssistThread.Start() >= 0) {
  297. if (realtime && fAssistThread.AcquireRealTime(priority) != 0) {
  298. jack_error("JackOSSChannel::StartAssistThread realtime priority failed.");
  299. }
  300. return true;
  301. }
  302. return false;
  303. }
  304. bool JackOSSChannel::StopAssistThread()
  305. {
  306. if (fAssistThread.GetStatus() != JackThread::kIdle) {
  307. fAssistThread.SetStatus(JackThread::kIdle);
  308. SignalWork();
  309. fAssistThread.Kill();
  310. }
  311. return true;
  312. }
  313. bool JackOSSChannel::CheckTimeAndRun()
  314. {
  315. // Check current frame time.
  316. if (!fFrameClock.now(fFrameStamp)) {
  317. jack_error("JackOSSChannel::CheckTimeAndRun(): Frame clock failed.");
  318. return false;
  319. }
  320. std::int64_t now = fFrameStamp;
  321. // Process read channel if wakeup time passed, or OSS buffer data available.
  322. if (fReadChannel.recording() && !fReadChannel.total_finished(now)) {
  323. if (now >= fReadChannel.wakeup_time(now)) {
  324. if (!fReadChannel.process(now)) {
  325. jack_error("JackOSSChannel::CheckTimeAndRun(): Read process failed.");
  326. return false;
  327. }
  328. }
  329. }
  330. // Process write channel if wakeup time passed, or OSS buffer space available.
  331. if (fWriteChannel.playback() && !fWriteChannel.total_finished(now)) {
  332. if (now >= fWriteChannel.wakeup_time(now)) {
  333. if (!fWriteChannel.process(now)) {
  334. jack_error("JackOSSChannel::CheckTimeAndRun(): Write process failed.");
  335. return false;
  336. }
  337. }
  338. }
  339. return true;
  340. }
  341. bool JackOSSChannel::Sleep() const
  342. {
  343. std::int64_t wakeup = NextWakeup();
  344. if (wakeup > fFrameStamp) {
  345. return fFrameClock.sleep(wakeup);
  346. }
  347. return true;
  348. }
  349. bool JackOSSChannel::CaptureFinished() const
  350. {
  351. return fReadChannel.finished(fFrameStamp);
  352. }
  353. bool JackOSSChannel::PlaybackFinished() const
  354. {
  355. return fWriteChannel.finished(fFrameStamp);
  356. }
  357. std::int64_t JackOSSChannel::PlaybackCorrection()
  358. {
  359. std::int64_t correction = 0;
  360. // If both channels are used, correct drift relative to recording balance.
  361. if (fReadChannel.recording() && fWriteChannel.playback()) {
  362. std::int64_t previous = fCorrection.correction();
  363. correction = fCorrection.correct(fWriteChannel.balance(), fReadChannel.balance());
  364. if (correction != previous) {
  365. jack_info("Playback correction changed from %lld to %lld.", previous, correction);
  366. jack_info("Read balance %lld vs write balance %lld.", fReadChannel.balance(), fWriteChannel.balance());
  367. }
  368. }
  369. return correction;
  370. }
  371. bool JackOSSChannel::Init()
  372. {
  373. return true;
  374. }
  375. bool JackOSSChannel::Execute()
  376. {
  377. if (Lock()) {
  378. if (fAssistThread.GetStatus() != JackThread::kIdle) {
  379. if (!CheckTimeAndRun()) {
  380. return Unlock() && false;
  381. }
  382. std::int64_t wakeup = NextWakeup();
  383. if (fReadChannel.total_finished(fFrameStamp) && fWriteChannel.total_finished(fFrameStamp)) {
  384. // Nothing to do, wait on the mutex for work.
  385. jack_info("JackOSSChannel::Execute waiting for work.");
  386. fMutex.TimedWait(1000000);
  387. jack_info("JackOSSChannel::Execute resuming work.");
  388. } else if (fFrameStamp < wakeup) {
  389. // Unlock mutex before going to sleep, let others process.
  390. return Unlock() && fFrameClock.sleep(wakeup);
  391. }
  392. }
  393. return Unlock();
  394. }
  395. return false;
  396. }
  397. std::int64_t JackOSSChannel::XRunGap() const
  398. {
  399. // Compute processing gap in case we are late.
  400. std::int64_t max_end = std::max(fReadChannel.total_end(), fWriteChannel.total_end());
  401. if (max_end < fFrameStamp) {
  402. return fFrameStamp - max_end;
  403. }
  404. return 0;
  405. }
  406. void JackOSSChannel::ResetBuffers(std::int64_t offset)
  407. {
  408. // Clear buffers and offset their positions, after processing gaps.
  409. if (fReadChannel.recording()) {
  410. fReadChannel.reset_buffers(fReadChannel.end_frames() + offset);
  411. }
  412. if (fWriteChannel.playback()) {
  413. fWriteChannel.reset_buffers(fWriteChannel.end_frames() + offset);
  414. }
  415. }
  416. std::int64_t JackOSSChannel::NextWakeup() const
  417. {
  418. return std::min(fReadChannel.wakeup_time(fFrameStamp), fWriteChannel.wakeup_time(fFrameStamp));
  419. }
  420. } // end of namespace