openmpt123.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. /*
  2. * openmpt123.hpp
  3. * --------------
  4. * Purpose: libopenmpt command line player
  5. * Notes : (currently none)
  6. * Authors: OpenMPT Devs
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #ifndef OPENMPT123_HPP
  10. #define OPENMPT123_HPP
  11. #include "openmpt123_config.hpp"
  12. #include "mpt/base/compiletime_warning.hpp"
  13. #include "mpt/base/floatingpoint.hpp"
  14. #include "mpt/base/preprocessor.hpp"
  15. #include "mpt/string_transcode/transcode.hpp"
  16. #include <string>
  17. namespace openmpt123 {
  18. struct exception : public openmpt::exception {
  19. exception( const std::string & text ) : openmpt::exception(text) { }
  20. };
  21. struct show_help_exception {
  22. std::string message;
  23. bool longhelp;
  24. show_help_exception( const std::string & msg = "", bool longhelp_ = true ) : message(msg), longhelp(longhelp_) { }
  25. };
  26. struct args_error_exception {
  27. args_error_exception() { }
  28. };
  29. struct show_help_keyboard_exception { };
  30. #if defined(WIN32)
  31. bool IsConsole( DWORD stdHandle );
  32. #endif
  33. bool IsTerminal( int fd );
  34. struct field {
  35. std::string key;
  36. std::string val;
  37. field( const std::string & key )
  38. : key(key)
  39. {
  40. return;
  41. }
  42. };
  43. class textout : public std::ostringstream {
  44. public:
  45. textout() {
  46. return;
  47. }
  48. virtual ~textout() {
  49. return;
  50. }
  51. protected:
  52. std::string pop() {
  53. std::string text = str();
  54. str(std::string());
  55. return text;
  56. }
  57. public:
  58. virtual void writeout() = 0;
  59. virtual void cursor_up( std::size_t lines ) {
  60. static_cast<void>( lines );
  61. }
  62. };
  63. class textout_dummy : public textout {
  64. public:
  65. textout_dummy() {
  66. return;
  67. }
  68. virtual ~textout_dummy() {
  69. return;
  70. }
  71. public:
  72. void writeout() override {
  73. static_cast<void>( pop() );
  74. }
  75. };
  76. class textout_ostream : public textout {
  77. private:
  78. std::ostream & s;
  79. #if defined(__DJGPP__)
  80. mpt::common_encoding codepage;
  81. #endif
  82. public:
  83. textout_ostream( std::ostream & s_ )
  84. : s(s_)
  85. #if defined(__DJGPP__)
  86. , codepage(mpt::common_encoding::cp437)
  87. #endif
  88. {
  89. #if defined(__DJGPP__)
  90. codepage = mpt::djgpp_get_locale_encoding();
  91. #endif
  92. return;
  93. }
  94. virtual ~textout_ostream() {
  95. writeout_impl();
  96. }
  97. private:
  98. void writeout_impl() {
  99. std::string text = pop();
  100. if ( text.length() > 0 ) {
  101. #if defined(__DJGPP__)
  102. s << mpt::transcode<std::string>( codepage, mpt::common_encoding::utf8, text );
  103. #elif defined(__EMSCRIPTEN__)
  104. s << text;
  105. #else
  106. s << mpt::transcode<std::string>( mpt::logical_encoding::locale, mpt::common_encoding::utf8, text );
  107. #endif
  108. s.flush();
  109. }
  110. }
  111. public:
  112. void writeout() override {
  113. writeout_impl();
  114. }
  115. void cursor_up( std::size_t lines ) override {
  116. s.flush();
  117. for ( std::size_t line = 0; line < lines; ++line ) {
  118. *this << "\x1b[1A";
  119. }
  120. }
  121. };
  122. #if defined(WIN32)
  123. class textout_ostream_console : public textout {
  124. private:
  125. #if defined(UNICODE)
  126. std::wostream & s;
  127. #else
  128. std::ostream & s;
  129. #endif
  130. HANDLE handle;
  131. bool console;
  132. public:
  133. #if defined(UNICODE)
  134. textout_ostream_console( std::wostream & s_, DWORD stdHandle_ )
  135. #else
  136. textout_ostream_console( std::ostream & s_, DWORD stdHandle_ )
  137. #endif
  138. : s(s_)
  139. , handle(GetStdHandle( stdHandle_ ))
  140. , console(IsConsole( stdHandle_ ))
  141. {
  142. return;
  143. }
  144. virtual ~textout_ostream_console() {
  145. writeout_impl();
  146. }
  147. private:
  148. void writeout_impl() {
  149. std::string text = pop();
  150. if ( text.length() > 0 ) {
  151. if ( console ) {
  152. #if defined(UNICODE)
  153. std::wstring wtext = mpt::transcode<std::wstring>( mpt::common_encoding::utf8, text );
  154. WriteConsole( handle, wtext.data(), static_cast<DWORD>( wtext.size() ), NULL, NULL );
  155. #else
  156. std::string ltext = mpt::transcode<std::string>( mpt::logical_encoding::locale, mpt::common_encoding::utf8, text );
  157. WriteConsole( handle, ltext.data(), static_cast<DWORD>( ltext.size() ), NULL, NULL );
  158. #endif
  159. } else {
  160. #if defined(UNICODE)
  161. s << mpt::transcode<std::wstring>( mpt::common_encoding::utf8, text );
  162. #else
  163. s << mpt::transcode<std::string>( mpt::logical_encoding::locale, mpt::common_encoding::utf8, text );
  164. #endif
  165. s.flush();
  166. }
  167. }
  168. }
  169. public:
  170. void writeout() override {
  171. writeout_impl();
  172. }
  173. void cursor_up( std::size_t lines ) override {
  174. if ( console ) {
  175. s.flush();
  176. CONSOLE_SCREEN_BUFFER_INFO csbi;
  177. ZeroMemory( &csbi, sizeof( CONSOLE_SCREEN_BUFFER_INFO ) );
  178. COORD coord_cursor = COORD();
  179. if ( GetConsoleScreenBufferInfo( handle, &csbi ) != FALSE ) {
  180. coord_cursor = csbi.dwCursorPosition;
  181. coord_cursor.X = 1;
  182. coord_cursor.Y -= static_cast<SHORT>( lines );
  183. SetConsoleCursorPosition( handle, coord_cursor );
  184. }
  185. }
  186. }
  187. };
  188. #endif // WIN32
  189. static inline float mpt_round( float val ) {
  190. if ( val >= 0.0f ) {
  191. return std::floor( val + 0.5f );
  192. } else {
  193. return std::ceil( val - 0.5f );
  194. }
  195. }
  196. static inline long mpt_lround( float val ) {
  197. return static_cast< long >( mpt_round( val ) );
  198. }
  199. static inline std::string append_software_tag( std::string software ) {
  200. std::string openmpt123 = std::string() + "openmpt123 " + OPENMPT123_VERSION_STRING + " (libopenmpt " + openmpt::string::get( "library_version" ) + ", OpenMPT " + openmpt::string::get( "core_version" ) + ")";
  201. if ( software.empty() ) {
  202. software = openmpt123;
  203. } else {
  204. software += " (via " + openmpt123 + ")";
  205. }
  206. return software;
  207. }
  208. static inline std::string get_encoder_tag() {
  209. return std::string() + "openmpt123 " + OPENMPT123_VERSION_STRING + " (libopenmpt " + openmpt::string::get( "library_version" ) + ", OpenMPT " + openmpt::string::get( "core_version" ) + ")";
  210. }
  211. static inline std::string get_extension( std::string filename ) {
  212. if ( filename.find_last_of( "." ) != std::string::npos ) {
  213. return filename.substr( filename.find_last_of( "." ) + 1 );
  214. }
  215. return "";
  216. }
  217. enum class Mode {
  218. None,
  219. Probe,
  220. Info,
  221. UI,
  222. Batch,
  223. Render
  224. };
  225. static inline std::string mode_to_string( Mode mode ) {
  226. switch ( mode ) {
  227. case Mode::None: return "none"; break;
  228. case Mode::Probe: return "probe"; break;
  229. case Mode::Info: return "info"; break;
  230. case Mode::UI: return "ui"; break;
  231. case Mode::Batch: return "batch"; break;
  232. case Mode::Render: return "render"; break;
  233. }
  234. return "";
  235. }
  236. static const std::int32_t default_low = -2;
  237. static const std::int32_t default_high = -1;
  238. struct commandlineflags {
  239. Mode mode;
  240. bool canUI;
  241. std::int32_t ui_redraw_interval;
  242. bool canProgress;
  243. std::string driver;
  244. std::string device;
  245. std::int32_t buffer;
  246. std::int32_t period;
  247. std::int32_t samplerate;
  248. std::int32_t channels;
  249. std::int32_t gain;
  250. std::int32_t separation;
  251. std::int32_t filtertaps;
  252. std::int32_t ramping; // ramping strength : -1:default 0:off 1 2 3 4 5 // roughly milliseconds
  253. std::int32_t tempo;
  254. std::int32_t pitch;
  255. std::int32_t dither;
  256. std::int32_t repeatcount;
  257. std::int32_t subsong;
  258. std::map<std::string, std::string> ctls;
  259. double seek_target;
  260. double end_time;
  261. bool quiet;
  262. bool verbose;
  263. int terminal_width;
  264. int terminal_height;
  265. bool show_details;
  266. bool show_message;
  267. bool show_ui;
  268. bool show_progress;
  269. bool show_meters;
  270. bool show_channel_meters;
  271. bool show_pattern;
  272. bool use_float;
  273. bool use_stdout;
  274. bool randomize;
  275. bool shuffle;
  276. bool restart;
  277. std::size_t playlist_index;
  278. std::vector<std::string> filenames;
  279. std::string output_filename;
  280. std::string output_extension;
  281. bool force_overwrite;
  282. bool paused;
  283. std::string warnings;
  284. void apply_default_buffer_sizes() {
  285. if ( ui_redraw_interval == default_high ) {
  286. ui_redraw_interval = 50;
  287. } else if ( ui_redraw_interval == default_low ) {
  288. ui_redraw_interval = 10;
  289. }
  290. if ( buffer == default_high ) {
  291. buffer = 250;
  292. } else if ( buffer == default_low ) {
  293. buffer = 50;
  294. }
  295. if ( period == default_high ) {
  296. period = 50;
  297. } else if ( period == default_low ) {
  298. period = 10;
  299. }
  300. }
  301. commandlineflags() {
  302. mode = Mode::UI;
  303. ui_redraw_interval = default_high;
  304. driver = "";
  305. device = "";
  306. buffer = default_high;
  307. period = default_high;
  308. #if defined(__DJGPP__)
  309. samplerate = 44100;
  310. channels = 2;
  311. use_float = false;
  312. #else
  313. samplerate = 48000;
  314. channels = 2;
  315. use_float = mpt::float_traits<float>::is_hard && mpt::float_traits<float>::is_ieee754_binary;
  316. #endif
  317. gain = 0;
  318. separation = 100;
  319. filtertaps = 8;
  320. ramping = -1;
  321. tempo = 0;
  322. pitch = 0;
  323. dither = 1;
  324. repeatcount = 0;
  325. subsong = -1;
  326. seek_target = 0.0;
  327. end_time = 0.0;
  328. quiet = false;
  329. verbose = false;
  330. #if defined(__DJGPP__)
  331. terminal_width = 80;
  332. terminal_height = 25;
  333. #else
  334. terminal_width = 72;
  335. terminal_height = 23;
  336. #endif
  337. #if defined(WIN32)
  338. terminal_width = 72;
  339. terminal_height = 23;
  340. HANDLE hStdOutput = GetStdHandle( STD_OUTPUT_HANDLE );
  341. if ( ( hStdOutput != NULL ) && ( hStdOutput != INVALID_HANDLE_VALUE ) ) {
  342. CONSOLE_SCREEN_BUFFER_INFO csbi;
  343. ZeroMemory( &csbi, sizeof( CONSOLE_SCREEN_BUFFER_INFO ) );
  344. if ( GetConsoleScreenBufferInfo( hStdOutput, &csbi ) != FALSE ) {
  345. terminal_width = std::min( static_cast<int>( 1 + csbi.srWindow.Right - csbi.srWindow.Left ), static_cast<int>( csbi.dwSize.X ) );
  346. terminal_height = std::min( static_cast<int>( 1 + csbi.srWindow.Bottom - csbi.srWindow.Top ), static_cast<int>( csbi.dwSize.Y ) );
  347. }
  348. }
  349. #else // WIN32
  350. if ( isatty( STDERR_FILENO ) ) {
  351. const char * env_columns = std::getenv( "COLUMNS" );
  352. if ( env_columns ) {
  353. std::istringstream istr( env_columns );
  354. int tmp = 0;
  355. istr >> tmp;
  356. if ( tmp > 0 ) {
  357. terminal_width = tmp;
  358. }
  359. }
  360. const char * env_rows = std::getenv( "ROWS" );
  361. if ( env_rows ) {
  362. std::istringstream istr( env_rows );
  363. int tmp = 0;
  364. istr >> tmp;
  365. if ( tmp > 0 ) {
  366. terminal_height = tmp;
  367. }
  368. }
  369. #if defined(TIOCGWINSZ)
  370. struct winsize ts;
  371. if ( ioctl( STDERR_FILENO, TIOCGWINSZ, &ts ) >= 0 ) {
  372. terminal_width = ts.ws_col;
  373. terminal_height = ts.ws_row;
  374. }
  375. #elif defined(TIOCGSIZE)
  376. struct ttysize ts;
  377. if ( ioctl( STDERR_FILENO, TIOCGSIZE, &ts ) >= 0 ) {
  378. terminal_width = ts.ts_cols;
  379. terminal_height = ts.ts_rows;
  380. }
  381. #endif
  382. }
  383. #endif
  384. show_details = true;
  385. show_message = false;
  386. #if defined(WIN32)
  387. canUI = IsTerminal( 0 ) ? true : false;
  388. canProgress = IsTerminal( 2 ) ? true : false;
  389. #else // !WIN32
  390. canUI = isatty( STDIN_FILENO ) ? true : false;
  391. canProgress = isatty( STDERR_FILENO ) ? true : false;
  392. #endif // WIN32
  393. show_ui = canUI;
  394. show_progress = canProgress;
  395. show_meters = canUI && canProgress;
  396. show_channel_meters = false;
  397. show_pattern = false;
  398. use_stdout = false;
  399. randomize = false;
  400. shuffle = false;
  401. restart = false;
  402. playlist_index = 0;
  403. output_extension = "auto";
  404. force_overwrite = false;
  405. paused = false;
  406. }
  407. void check_and_sanitize() {
  408. if ( filenames.size() == 0 ) {
  409. throw args_error_exception();
  410. }
  411. if ( use_stdout && ( device != commandlineflags().device || !output_filename.empty() ) ) {
  412. throw args_error_exception();
  413. }
  414. if ( !output_filename.empty() && ( device != commandlineflags().device || use_stdout ) ) {
  415. throw args_error_exception();
  416. }
  417. for ( const auto & filename : filenames ) {
  418. if ( filename == "-" ) {
  419. canUI = false;
  420. }
  421. }
  422. show_ui = canUI;
  423. if ( mode == Mode::None ) {
  424. if ( canUI ) {
  425. mode = Mode::UI;
  426. } else {
  427. mode = Mode::Batch;
  428. }
  429. }
  430. if ( mode == Mode::UI && !canUI ) {
  431. throw args_error_exception();
  432. }
  433. if ( show_progress && !canProgress ) {
  434. throw args_error_exception();
  435. }
  436. switch ( mode ) {
  437. case Mode::None:
  438. throw args_error_exception();
  439. break;
  440. case Mode::Probe:
  441. show_ui = false;
  442. show_progress = false;
  443. show_meters = false;
  444. show_channel_meters = false;
  445. show_pattern = false;
  446. break;
  447. case Mode::Info:
  448. show_ui = false;
  449. show_progress = false;
  450. show_meters = false;
  451. show_channel_meters = false;
  452. show_pattern = false;
  453. break;
  454. case Mode::UI:
  455. break;
  456. case Mode::Batch:
  457. show_meters = false;
  458. show_channel_meters = false;
  459. show_pattern = false;
  460. break;
  461. case Mode::Render:
  462. show_meters = false;
  463. show_channel_meters = false;
  464. show_pattern = false;
  465. show_ui = false;
  466. break;
  467. }
  468. if ( quiet ) {
  469. verbose = false;
  470. show_ui = false;
  471. show_details = false;
  472. show_progress = false;
  473. show_channel_meters = false;
  474. }
  475. if ( verbose ) {
  476. show_details = true;
  477. }
  478. if ( channels != 1 && channels != 2 && channels != 4 ) {
  479. channels = commandlineflags().channels;
  480. }
  481. if ( samplerate < 0 ) {
  482. samplerate = commandlineflags().samplerate;
  483. }
  484. if ( output_extension == "auto" ) {
  485. output_extension = "";
  486. }
  487. if ( mode != Mode::Render && !output_extension.empty() ) {
  488. throw args_error_exception();
  489. }
  490. if ( mode == Mode::Render && !output_filename.empty() ) {
  491. throw args_error_exception();
  492. }
  493. if ( mode != Mode::Render && !output_filename.empty() ) {
  494. output_extension = get_extension( output_filename );
  495. }
  496. if ( output_extension.empty() ) {
  497. output_extension = "wav";
  498. }
  499. }
  500. };
  501. template < typename Tsample > Tsample convert_sample_to( float val );
  502. template < > float convert_sample_to( float val ) {
  503. return val;
  504. }
  505. template < > std::int16_t convert_sample_to( float val ) {
  506. std::int32_t tmp = static_cast<std::int32_t>( val * 32768.0f );
  507. tmp = std::min( tmp, std::int32_t( 32767 ) );
  508. tmp = std::max( tmp, std::int32_t( -32768 ) );
  509. return static_cast<std::int16_t>( tmp );
  510. }
  511. class write_buffers_interface {
  512. protected:
  513. virtual ~write_buffers_interface() {
  514. return;
  515. }
  516. public:
  517. virtual void write_metadata( std::map<std::string,std::string> metadata ) {
  518. (void)metadata;
  519. return;
  520. }
  521. virtual void write_updated_metadata( std::map<std::string,std::string> metadata ) {
  522. (void)metadata;
  523. return;
  524. }
  525. virtual void write( const std::vector<float*> buffers, std::size_t frames ) = 0;
  526. virtual void write( const std::vector<std::int16_t*> buffers, std::size_t frames ) = 0;
  527. virtual bool pause() {
  528. return false;
  529. }
  530. virtual bool unpause() {
  531. return false;
  532. }
  533. virtual bool sleep( int /*ms*/ ) {
  534. return false;
  535. }
  536. virtual bool is_dummy() const {
  537. return false;
  538. }
  539. };
  540. class write_buffers_polling_wrapper : public write_buffers_interface {
  541. protected:
  542. std::size_t channels;
  543. std::size_t sampleQueueMaxFrames;
  544. std::deque<float> sampleQueue;
  545. protected:
  546. virtual ~write_buffers_polling_wrapper() {
  547. return;
  548. }
  549. protected:
  550. write_buffers_polling_wrapper( const commandlineflags & flags )
  551. : channels(flags.channels)
  552. , sampleQueueMaxFrames(0)
  553. {
  554. return;
  555. }
  556. void set_queue_size_frames( std::size_t frames ) {
  557. sampleQueueMaxFrames = frames;
  558. }
  559. template < typename Tsample >
  560. Tsample pop_queue() {
  561. float val = 0.0f;
  562. if ( !sampleQueue.empty() ) {
  563. val = sampleQueue.front();
  564. sampleQueue.pop_front();
  565. }
  566. return convert_sample_to<Tsample>( val );
  567. }
  568. public:
  569. void write( const std::vector<float*> buffers, std::size_t frames ) override {
  570. for ( std::size_t frame = 0; frame < frames; ++frame ) {
  571. for ( std::size_t channel = 0; channel < channels; ++channel ) {
  572. sampleQueue.push_back( buffers[channel][frame] );
  573. }
  574. while ( sampleQueue.size() >= sampleQueueMaxFrames * channels ) {
  575. while ( !forward_queue() ) {
  576. sleep( 1 );
  577. }
  578. }
  579. }
  580. }
  581. void write( const std::vector<std::int16_t*> buffers, std::size_t frames ) override {
  582. for ( std::size_t frame = 0; frame < frames; ++frame ) {
  583. for ( std::size_t channel = 0; channel < channels; ++channel ) {
  584. sampleQueue.push_back( buffers[channel][frame] * (1.0f/32768.0f) );
  585. }
  586. while ( sampleQueue.size() >= sampleQueueMaxFrames * channels ) {
  587. while ( !forward_queue() ) {
  588. sleep( 1 );
  589. }
  590. }
  591. }
  592. }
  593. virtual bool forward_queue() = 0;
  594. bool sleep( int ms ) override = 0;
  595. };
  596. class write_buffers_polling_wrapper_int : public write_buffers_interface {
  597. protected:
  598. std::size_t channels;
  599. std::size_t sampleQueueMaxFrames;
  600. std::deque<std::int16_t> sampleQueue;
  601. protected:
  602. virtual ~write_buffers_polling_wrapper_int() {
  603. return;
  604. }
  605. protected:
  606. write_buffers_polling_wrapper_int( const commandlineflags & flags )
  607. : channels(flags.channels)
  608. , sampleQueueMaxFrames(0)
  609. {
  610. return;
  611. }
  612. void set_queue_size_frames( std::size_t frames ) {
  613. sampleQueueMaxFrames = frames;
  614. }
  615. std::int16_t pop_queue() {
  616. std::int16_t val = 0;
  617. if ( !sampleQueue.empty() ) {
  618. val = sampleQueue.front();
  619. sampleQueue.pop_front();
  620. }
  621. return val;
  622. }
  623. public:
  624. void write( const std::vector<float*> buffers, std::size_t frames ) override {
  625. for ( std::size_t frame = 0; frame < frames; ++frame ) {
  626. for ( std::size_t channel = 0; channel < channels; ++channel ) {
  627. sampleQueue.push_back( convert_sample_to<std::int16_t>( buffers[channel][frame] ) );
  628. }
  629. while ( sampleQueue.size() >= sampleQueueMaxFrames * channels ) {
  630. while ( !forward_queue() ) {
  631. sleep( 1 );
  632. }
  633. }
  634. }
  635. }
  636. void write( const std::vector<std::int16_t*> buffers, std::size_t frames ) override {
  637. for ( std::size_t frame = 0; frame < frames; ++frame ) {
  638. for ( std::size_t channel = 0; channel < channels; ++channel ) {
  639. sampleQueue.push_back( buffers[channel][frame] );
  640. }
  641. while ( sampleQueue.size() >= sampleQueueMaxFrames * channels ) {
  642. while ( !forward_queue() ) {
  643. sleep( 1 );
  644. }
  645. }
  646. }
  647. }
  648. virtual bool forward_queue() = 0;
  649. bool sleep( int ms ) override = 0;
  650. };
  651. class void_audio_stream : public write_buffers_interface {
  652. public:
  653. virtual ~void_audio_stream() {
  654. return;
  655. }
  656. public:
  657. void write( const std::vector<float*> buffers, std::size_t frames ) override {
  658. (void)buffers;
  659. (void)frames;
  660. }
  661. void write( const std::vector<std::int16_t*> buffers, std::size_t frames ) override {
  662. (void)buffers;
  663. (void)frames;
  664. }
  665. bool is_dummy() const override {
  666. return true;
  667. }
  668. };
  669. class file_audio_stream_base : public write_buffers_interface {
  670. protected:
  671. file_audio_stream_base() {
  672. return;
  673. }
  674. public:
  675. void write_metadata( std::map<std::string,std::string> metadata ) override {
  676. (void)metadata;
  677. return;
  678. }
  679. void write_updated_metadata( std::map<std::string,std::string> metadata ) override {
  680. (void)metadata;
  681. return;
  682. }
  683. void write( const std::vector<float*> buffers, std::size_t frames ) override = 0;
  684. void write( const std::vector<std::int16_t*> buffers, std::size_t frames ) override = 0;
  685. virtual ~file_audio_stream_base() {
  686. return;
  687. }
  688. };
  689. } // namespace openmpt123
  690. #endif // OPENMPT123_HPP