aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/Input/in_mod-openmpt/ExtendedRead.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Plugins/Input/in_mod-openmpt/ExtendedRead.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Plugins/Input/in_mod-openmpt/ExtendedRead.cpp')
-rw-r--r--Src/Plugins/Input/in_mod-openmpt/ExtendedRead.cpp139
1 files changed, 139 insertions, 0 deletions
diff --git a/Src/Plugins/Input/in_mod-openmpt/ExtendedRead.cpp b/Src/Plugins/Input/in_mod-openmpt/ExtendedRead.cpp
new file mode 100644
index 00000000..646b3807
--- /dev/null
+++ b/Src/Plugins/Input/in_mod-openmpt/ExtendedRead.cpp
@@ -0,0 +1,139 @@
+#include "api__in_mod.h"
+#include <libopenmpt/libopenmpt.h>
+#include "../nsutil/pcm.h"
+
+static const size_t kModBufferSize = 512;
+static const unsigned int kModSampleRate = 44100; // TODO(benski) configurable!
+
+openmpt_module *OpenMod(const wchar_t *filename);
+
+class PlayParams
+{
+public:
+ PlayParams();
+ ~PlayParams();
+ openmpt_module *mod;
+ float *buffer;
+ int bps;
+ int channels;
+ int sample_rate;
+ bool use_float;
+ size_t (*openmpt_read)(openmpt_module * mod, int32_t samplerate, size_t count, float *interleaved_stereo);
+};
+
+PlayParams::PlayParams()
+{
+ mod = 0;
+ buffer = 0;
+}
+
+PlayParams::~PlayParams()
+{
+ openmpt_module_destroy(mod);
+ free(buffer);
+
+}
+
+static PlayParams *ExtendedOpen(const wchar_t *fn, int *size, int *bps, int *nch, int *srate, bool use_float)
+{
+ float *float_buffer = 0;
+ size_t (*openmpt_read)(openmpt_module * mod, int32_t samplerate, size_t count, float *interleaved_stereo)=openmpt_module_read_interleaved_float_stereo;
+
+ openmpt_module *mod = OpenMod(fn);
+ if (!mod) {
+ return 0;
+ }
+
+ int requested_channels = *nch;
+ int requested_bits = *bps;
+ int requested_srate = *srate;
+
+ if (!requested_channels) {
+ requested_channels=2;
+ }
+
+ if (!requested_bits) {
+ if (use_float) {
+ requested_bits=32;
+ } else {
+ requested_bits=16;
+ }
+ }
+
+ if (!requested_srate) {
+ requested_srate = kModSampleRate;
+ }
+
+ if (requested_channels == 1) {
+ openmpt_read = openmpt_module_read_float_mono;
+ } else if (requested_channels < 4) {
+ requested_channels = 2;
+ openmpt_read = openmpt_module_read_interleaved_float_stereo;
+ } else if (requested_channels) {
+ requested_channels = 4;
+ openmpt_read = openmpt_module_read_interleaved_float_quad;
+ }
+
+ if (!use_float) {
+ float_buffer = (float *)malloc(sizeof(float) * kModBufferSize * requested_channels);
+ if (!float_buffer) {
+ openmpt_module_destroy(mod);
+ return 0;
+ }
+ }
+
+ PlayParams *play_params = new PlayParams;
+ if (!play_params) {
+ openmpt_module_destroy(mod);
+ free(float_buffer);
+ return 0;
+ }
+
+ play_params->mod = mod;
+ play_params->buffer = float_buffer;
+ play_params->bps = requested_bits;
+ play_params->channels = requested_channels;
+ play_params->use_float = use_float;
+ play_params->openmpt_read = openmpt_read;
+ play_params->sample_rate = requested_srate;
+
+ *nch = requested_channels;
+ *srate = requested_srate;
+ *bps = requested_bits;
+
+ *size = (int)(openmpt_module_get_duration_seconds(mod) * (double)requested_bits * (double)requested_srate * (double)requested_channels / 8.0);
+
+ return play_params;
+}
+extern "C" __declspec(dllexport) intptr_t winampGetExtendedRead_openW_float(const wchar_t *fn, int *size, int *bps, int *nch, int *srate)
+{
+ return (intptr_t)ExtendedOpen(fn, size, bps, nch, srate, true);
+}
+
+extern "C" __declspec(dllexport) intptr_t winampGetExtendedRead_openW(const wchar_t *fn, int *size, int *bps, int *nch, int *srate)
+{
+ return (intptr_t)ExtendedOpen(fn, size, bps, nch, srate, false);
+}
+
+extern "C" __declspec(dllexport) size_t winampGetExtendedRead_getData(intptr_t handle, char *dest, size_t len, int *killswitch)
+{
+ PlayParams *play_params = (PlayParams *)handle;
+ size_t requested_samples = len / (play_params->channels * play_params->bps/8);
+
+ if (play_params->use_float) {
+ return play_params->openmpt_read(play_params->mod, play_params->sample_rate, requested_samples, (float *)dest) * sizeof(float) * play_params->channels;
+ } else {
+ if (requested_samples > kModBufferSize) {
+ requested_samples = kModBufferSize;
+ }
+ size_t count = play_params->openmpt_read(play_params->mod, play_params->sample_rate, requested_samples, play_params->buffer);
+ nsutil_pcm_FloatToInt_Interleaved(dest, play_params->buffer, play_params->bps, play_params->channels*count);
+ return count * play_params->bps * play_params->channels / 8;
+ }
+}
+
+extern "C" __declspec(dllexport) void winampGetExtendedRead_close(intptr_t handle)
+{
+ PlayParams *play_params = (PlayParams *)handle;
+ delete play_params;
+} \ No newline at end of file