diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Plugins/Input/in_midi/sampling.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-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.cpp | 333 |
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 |