ExtendedRead.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #include "api__in_mod.h"
  2. #include <libopenmpt/libopenmpt.h>
  3. #include "../nsutil/pcm.h"
  4. static const size_t kModBufferSize = 512;
  5. static const unsigned int kModSampleRate = 44100; // TODO(benski) configurable!
  6. openmpt_module *OpenMod(const wchar_t *filename);
  7. class PlayParams
  8. {
  9. public:
  10. PlayParams();
  11. ~PlayParams();
  12. openmpt_module *mod;
  13. float *buffer;
  14. int bps;
  15. int channels;
  16. int sample_rate;
  17. bool use_float;
  18. size_t (*openmpt_read)(openmpt_module * mod, int32_t samplerate, size_t count, float *interleaved_stereo);
  19. };
  20. PlayParams::PlayParams()
  21. {
  22. mod = 0;
  23. buffer = 0;
  24. }
  25. PlayParams::~PlayParams()
  26. {
  27. openmpt_module_destroy(mod);
  28. free(buffer);
  29. }
  30. static PlayParams *ExtendedOpen(const wchar_t *fn, int *size, int *bps, int *nch, int *srate, bool use_float)
  31. {
  32. float *float_buffer = 0;
  33. size_t (*openmpt_read)(openmpt_module * mod, int32_t samplerate, size_t count, float *interleaved_stereo)=openmpt_module_read_interleaved_float_stereo;
  34. openmpt_module *mod = OpenMod(fn);
  35. if (!mod) {
  36. return 0;
  37. }
  38. int requested_channels = *nch;
  39. int requested_bits = *bps;
  40. int requested_srate = *srate;
  41. if (!requested_channels) {
  42. requested_channels=2;
  43. }
  44. if (!requested_bits) {
  45. if (use_float) {
  46. requested_bits=32;
  47. } else {
  48. requested_bits=16;
  49. }
  50. }
  51. if (!requested_srate) {
  52. requested_srate = kModSampleRate;
  53. }
  54. if (requested_channels == 1) {
  55. openmpt_read = openmpt_module_read_float_mono;
  56. } else if (requested_channels < 4) {
  57. requested_channels = 2;
  58. openmpt_read = openmpt_module_read_interleaved_float_stereo;
  59. } else if (requested_channels) {
  60. requested_channels = 4;
  61. openmpt_read = openmpt_module_read_interleaved_float_quad;
  62. }
  63. if (!use_float) {
  64. float_buffer = (float *)malloc(sizeof(float) * kModBufferSize * requested_channels);
  65. if (!float_buffer) {
  66. openmpt_module_destroy(mod);
  67. return 0;
  68. }
  69. }
  70. PlayParams *play_params = new PlayParams;
  71. if (!play_params) {
  72. openmpt_module_destroy(mod);
  73. free(float_buffer);
  74. return 0;
  75. }
  76. play_params->mod = mod;
  77. play_params->buffer = float_buffer;
  78. play_params->bps = requested_bits;
  79. play_params->channels = requested_channels;
  80. play_params->use_float = use_float;
  81. play_params->openmpt_read = openmpt_read;
  82. play_params->sample_rate = requested_srate;
  83. *nch = requested_channels;
  84. *srate = requested_srate;
  85. *bps = requested_bits;
  86. *size = (int)(openmpt_module_get_duration_seconds(mod) * (double)requested_bits * (double)requested_srate * (double)requested_channels / 8.0);
  87. return play_params;
  88. }
  89. extern "C" __declspec(dllexport) intptr_t winampGetExtendedRead_openW_float(const wchar_t *fn, int *size, int *bps, int *nch, int *srate)
  90. {
  91. return (intptr_t)ExtendedOpen(fn, size, bps, nch, srate, true);
  92. }
  93. extern "C" __declspec(dllexport) intptr_t winampGetExtendedRead_openW(const wchar_t *fn, int *size, int *bps, int *nch, int *srate)
  94. {
  95. return (intptr_t)ExtendedOpen(fn, size, bps, nch, srate, false);
  96. }
  97. extern "C" __declspec(dllexport) size_t winampGetExtendedRead_getData(intptr_t handle, char *dest, size_t len, int *killswitch)
  98. {
  99. PlayParams *play_params = (PlayParams *)handle;
  100. size_t requested_samples = len / (play_params->channels * play_params->bps/8);
  101. if (play_params->use_float) {
  102. return play_params->openmpt_read(play_params->mod, play_params->sample_rate, requested_samples, (float *)dest) * sizeof(float) * play_params->channels;
  103. } else {
  104. if (requested_samples > kModBufferSize) {
  105. requested_samples = kModBufferSize;
  106. }
  107. size_t count = play_params->openmpt_read(play_params->mod, play_params->sample_rate, requested_samples, play_params->buffer);
  108. nsutil_pcm_FloatToInt_Interleaved(dest, play_params->buffer, play_params->bps, play_params->channels*count);
  109. return count * play_params->bps * play_params->channels / 8;
  110. }
  111. }
  112. extern "C" __declspec(dllexport) void winampGetExtendedRead_close(intptr_t handle)
  113. {
  114. PlayParams *play_params = (PlayParams *)handle;
  115. delete play_params;
  116. }