aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/Input/in_midi/sampling.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_midi/sampling.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Plugins/Input/in_midi/sampling.cpp')
-rw-r--r--Src/Plugins/Input/in_midi/sampling.cpp333
1 files changed, 333 insertions, 0 deletions
diff --git a/Src/Plugins/Input/in_midi/sampling.cpp b/Src/Plugins/Input/in_midi/sampling.cpp
new file mode 100644
index 00000000..06c34653
--- /dev/null
+++ b/Src/Plugins/Input/in_midi/sampling.cpp
@@ -0,0 +1,333 @@
+#include "main.h"
+#include <ks.h>
+#include <ksmedia.h>
+#include <malloc.h>
+
+static void make_wfx(WAVEFORMATEX * wfx,int srate,int nch,int bps)
+{
+ wfx->wFormatTag=WAVE_FORMAT_PCM;
+ wfx->nChannels=nch;
+ wfx->nSamplesPerSec=srate;
+ wfx->nAvgBytesPerSec=srate*nch*(bps>>3);
+ wfx->nBlockAlign=nch * (bps>>3);
+ wfx->wBitsPerSample=bps;
+ wfx->cbSize=0;
+}
+
+static void make_wfxe(WAVEFORMATEXTENSIBLE * wfx,int srate,int nch,int bps)
+{
+ make_wfx(&wfx->Format,srate,nch,bps);
+ wfx->Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
+ wfx->Format.cbSize=22;
+ wfx->Samples.wReserved=0;
+ wfx->dwChannelMask=0;
+ wfx->SubFormat=KSDATAFORMAT_SUBTYPE_PCM;
+}
+
+#ifndef IN_MIDI_NO_WAVEIN_SOURCE
+
+extern cfg_int cfg_samp_revert;
+
+#define MMBOOL MIXERCONTROLDETAILS_BOOLEAN
+
+static MMBOOL *do_mixer_shit(DWORD param,DWORD type,BOOL store,UINT input,MMBOOL *tab)
+{
+ UINT id=0;
+ mixerGetID((HMIXEROBJ)param,&id,type);
+
+ MIXERCAPS caps;
+ mixerGetDevCaps(id,&caps,sizeof(caps));
+ MIXERLINE ml;
+ ZeroMemory(&ml,sizeof(ml));
+ ml.cbStruct=sizeof(ml);
+ ml.dwComponentType=MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
+
+ mixerGetLineInfo((HMIXEROBJ)id,&ml,MIXER_GETLINEINFOF_COMPONENTTYPE|MIXER_OBJECTF_MIXER);
+
+ MIXERLINECONTROLS cs;
+ MIXERCONTROL c;
+ ZeroMemory(&cs,sizeof(cs));
+ cs.cbStruct=sizeof(cs);
+ cs.cControls=1;
+ cs.dwLineID=ml.dwLineID;
+ cs.dwControlType=MIXERCONTROL_CONTROLTYPE_MUX;
+ cs.cbmxctrl=sizeof(c);
+ cs.pamxctrl=&c;
+ ZeroMemory(&c,sizeof(c));
+ c.cbStruct=sizeof(c);
+
+ if (!mixerGetLineControls((HMIXEROBJ)id,&cs,MIXER_OBJECTF_MIXER|MIXER_GETLINECONTROLSF_ONEBYTYPE))
+ {
+ if (store)
+ {
+ if (!tab)
+ {
+ tab=(MMBOOL*)alloca(sizeof(MMBOOL)*c.cMultipleItems);
+ memset(tab,0,sizeof(MMBOOL)*c.cMultipleItems);
+ tab[input].fValue=1;
+ }
+ }
+ else
+ {
+ if (!tab) tab=new MMBOOL[c.cMultipleItems];
+ }
+
+ if (tab)
+ {
+ MIXERCONTROLDETAILS d;
+ d.cbStruct=sizeof(d);
+ d.dwControlID=c.dwControlID;
+ d.cbDetails=sizeof(MMBOOL);
+ d.cChannels=ml.cChannels;
+ d.cMultipleItems=c.cMultipleItems;
+ d.paDetails=tab;
+
+ if (store) mixerSetControlDetails((HMIXEROBJ)id,&d,MIXER_SETCONTROLDETAILSF_VALUE |MIXER_OBJECTF_MIXER);
+ else mixerGetControlDetails((HMIXEROBJ)id,&d,MIXER_GETCONTROLDETAILSF_VALUE |MIXER_OBJECTF_MIXER);
+ }
+ }
+ return tab;
+}
+#endif
+
+class CVis : public CStream
+{
+private:
+#ifndef IN_MIDI_NO_WAVEIN_SOURCE
+ MMBOOL * old_settings;
+ UINT wavein_id;
+ void src_init()
+ {
+ wavein_id=(UINT)cfg_wavein_dev;
+ if (cfg_wavein_src)
+ {
+ if (cfg_samp_revert) old_settings = do_mixer_shit(wavein_id,MIXER_OBJECTF_WAVEIN,0,0,0);
+ do_mixer_shit(wavein_id,MIXER_OBJECTF_WAVEIN,1,cfg_wavein_src-1,0);
+ }
+ }
+ void src_deinit()
+ {
+ if (old_settings)
+ {
+ do_mixer_shit(wavein_id,MIXER_OBJECTF_WAVEIN,1,0,old_settings);
+ delete[] old_settings;
+ old_settings=0;
+ }
+ }
+#endif
+ bool eof;
+public:
+ bool init(int p_srate,int p_nch,int p_bps);
+ void Eof() {eof=1;}
+
+
+ virtual void Pause(int);
+ virtual UINT ReadData(void*,UINT,bool*);
+ virtual void Flush();
+ virtual ~CVis();
+ CVis()
+ {
+#ifndef IN_MIDI_NO_WAVEIN_SOURCE
+ old_settings=0;
+#endif
+ eof=0;buffer=0;blox=0;hWi=0;}
+
+private:
+ BYTE * buffer;
+ UINT bufsize;
+ UINT read_pos;
+ UINT data;
+ UINT blocksize;
+ HWAVEIN hWi;
+ WAVEHDR *blox;
+ UINT numblocks;
+ UINT cur_block,cur_done;
+ int paused;
+ UINT in_mm;
+ int srate,nch,bps;
+// void on_done(WAVEBUFFER*);
+};
+
+
+void CVis::Flush()
+{
+ if (paused) return;
+ waveInReset(hWi);
+ UINT n;
+ for(n=0;n<numblocks;n++)
+ {
+ blox[n].dwUser=0;
+ waveInAddBuffer(hWi,&blox[n],sizeof(WAVEHDR));
+ }
+
+ cur_block=0;
+ cur_done=0;
+ in_mm=numblocks;//added all blocks already
+
+ read_pos=0;
+ data=0;
+ waveInStart(hWi);
+}
+
+void CALLBACK waveInProc(HWAVEIN hWi,UINT msg,DWORD dwIns,DWORD p1,DWORD p2)
+{
+ if (msg==WIM_DATA && p1)
+ {
+ ((WAVEHDR*)p1)->dwUser=1;
+ }
+}
+
+bool CVis::init(int p_srate,int p_nch,int p_bps)
+{
+ srate=p_srate;
+ nch=p_nch;
+ bps=p_bps;
+ blocksize=576 * (bps/8) * (nch);
+ if (cfg_sampout) blocksize<<=3;
+ numblocks=(2 * srate * nch * (bps>>3))/blocksize;
+ bufsize=numblocks*blocksize;
+ blox=new WAVEHDR[numblocks];
+ memset(blox,0,sizeof(WAVEHDR)*numblocks);
+ buffer=(BYTE*)malloc(bufsize);
+
+ try
+ {
+ WAVEFORMATEX wfx;
+ make_wfx(&wfx,srate,nch,bps);
+ if (waveInOpen(&hWi,cfg_wavein_dev,&wfx,(DWORD)waveInProc,0,CALLBACK_FUNCTION))
+ {
+ WAVEFORMATEXTENSIBLE wfxe = {0};
+ make_wfxe(&wfxe,srate,nch,bps);
+ if (waveInOpen(&hWi,cfg_wavein_dev,&wfxe.Format,(DWORD)waveInProc,0,CALLBACK_FUNCTION))
+ {
+ return 0;
+ }
+ }
+ } catch(...)//gay drivers etc
+ {
+ return 0;
+ }
+#ifndef IN_MIDI_NO_WAVEIN_SOURCE
+ src_init();
+#endif
+
+ UINT n;
+ for(n=0;n<numblocks;n++)
+ {
+ blox[n].lpData=(char*)(buffer+blocksize*n);
+ blox[n].dwBufferLength=blocksize;
+ waveInPrepareHeader(hWi,&blox[n],sizeof(WAVEHDR));
+ }
+
+ paused=0;
+ Flush();
+#ifdef USE_LOG
+ log_write("sampling started OK");
+#endif
+ return 1;
+}
+
+CVis::~CVis()
+{
+#ifdef USE_LOG
+ log_write("shutting down sampling");
+#endif
+ if (hWi)
+ {
+ waveInReset(hWi);
+ UINT n;
+ for(n=0;n<numblocks;n++)
+ {
+ waveInUnprepareHeader(hWi,&blox[n],sizeof(WAVEHDR));
+ }
+
+#ifndef IN_MIDI_NO_WAVEIN_SOURCE
+ src_deinit();
+#endif
+ waveInClose(hWi);
+ hWi=0;
+ }
+#ifdef USE_LOG
+ log_write("sampling shut down OK");
+#endif
+ if (blox) delete[] blox;
+ if (buffer) free(buffer);
+}
+
+UINT CVis::ReadData(void * _dst,UINT bytes,bool * ks)
+{
+ if (eof) return 0;
+ BYTE * dst=(BYTE*)_dst;
+ if (paused) return 0;
+ while(!*ks)
+ {
+ while(blox[cur_done].dwUser)
+ {
+ blox[cur_done].dwUser=0;
+ cur_done=(cur_done+1)%numblocks;
+ in_mm--;
+ data+=blocksize;
+ }
+
+ {
+ UINT d=data;
+ if (d)
+ {
+ if (d>bytes) d=bytes;
+ if (read_pos+d>bufsize)
+ {
+ UINT foo=bufsize-read_pos;
+ memcpy(dst,buffer+read_pos,foo);
+ memcpy(dst+foo,buffer,read_pos=d-foo);
+ }
+ else
+ {
+ memcpy(dst,buffer+read_pos,d);
+ read_pos+=d;
+ }
+ dst+=d;
+ data-=d;
+ bytes-=d;
+ }
+ }
+
+
+ {
+ UINT max=numblocks-(data+blocksize-1)/blocksize;
+ while(in_mm < max)
+ {
+ waveInAddBuffer(hWi,&blox[cur_block],sizeof(WAVEHDR));
+ cur_block=(cur_block+1)%numblocks;
+ in_mm++;
+ }
+ }
+ if (!bytes) break;
+ MIDI_callback::Idle();
+ }
+
+ return dst-(BYTE*)_dst;
+}
+
+void CVis::Pause(int b)
+{
+ paused=b;
+ if (b)
+ {
+ waveInStop(hWi);
+ }
+ else
+ {
+ Flush();
+ }
+}
+
+CStream * sampling_create(int srate,int nch,int bps)
+{
+ CVis * ptr = new CVis;
+ if (!ptr->init(srate,nch,bps))
+ {
+ delete ptr;
+ ptr=0;
+ }
+ return ptr;
+} \ No newline at end of file