123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- #include "main.h"
- #include "../nsv/enc_if.h"
- #include <mmreg.h>
- #include <msacm.h>
- #include "WavEncoder.h"
- void initWfx();
- #define BUFSIZE 0x20000
- extern EXT_WFX convert_wfx;
- extern WAVEFORMATEX wfx_default;
- static DWORD FileTell(HANDLE hFile) { return SetFilePointer(hFile, 0, 0, FILE_CURRENT);}
- static void FileAlign(HANDLE hFile) {if (FileTell(hFile)&1) SetFilePointer(hFile, 1, 0, FILE_CURRENT);}
- #define rev32(X) ((((DWORD)(X)&0xFF)<<24)|(((DWORD)(X)&0xFF00)<<8)|(((DWORD)(X)&0xFF0000)>>8)|(((DWORD)(X)&0xFF000000)>>24))
- WavEncoder::WavEncoder(int srate, int nch, int bps, int res_srate , int res_bps, int res_nch )
- {
- m_did_header = 0;
- m_srate = srate;
- m_nch = nch;
- m_bps = bps;
- m_error = 0;
- hStream = 0;
- hStreamResample = 0;
- //_asm { int 3 };
- m_acm_resample_buf = NULL;
- m_acm_resample_outbuf = NULL;
- m_bytes_done = 0;
- m_hlen = 0;
- m_nsam = 0;
- if (res_srate && (res_srate != srate || res_bps != bps || res_nch != nch))
- {
- //manual resample (ie: burning)
- m_acm_buf = (unsigned char *)malloc(BUFSIZE);
- m_acm_outbuf = (unsigned char *)malloc(BUFSIZE);
- m_bytes_inbuf = 0;
- m_bytes_outbuf = 0;
- m_wfx_src.wFormatTag = WAVE_FORMAT_PCM;
- m_wfx_src.nChannels = nch;
- m_wfx_src.nSamplesPerSec = srate;
- m_wfx_src.nAvgBytesPerSec = srate * nch * (bps >> 3);
- m_wfx_src.nBlockAlign = nch * (bps >> 3);
- m_wfx_src.wBitsPerSample = bps;
- m_wfx_src.cbSize = 0;
- m_convert_wfx.wfx = wfx_default;
- m_convert_wfx.wfx.nSamplesPerSec = res_srate;
- m_convert_wfx.wfx.nChannels = res_nch;
- m_convert_wfx.wfx.wBitsPerSample = res_bps;
- m_convert_wfx.wfx.nAvgBytesPerSec = res_srate * res_nch * (res_bps / 8);
- m_convert_wfx.wfx.nBlockAlign = res_nch * (res_bps / 8);
- m_convert_wfx.wfx.cbSize = 0;
- MMRESULT rs = acmStreamOpen(&hStream, 0, &m_wfx_src, &m_convert_wfx.wfx, 0, 0, 0, ACM_STREAMOPENF_NONREALTIME);
- if (rs || !hStream)
- {
- m_error = 1;
- return ;
- }
- ZeroMemory(&ahd, sizeof(ahd));
- ahd.cbStruct = sizeof(ahd);
- ahd.pbSrc = m_acm_buf;
- ahd.cbSrcLength = BUFSIZE;
- ahd.pbDst = m_acm_outbuf;
- ahd.cbDstLength = BUFSIZE;
- if (acmStreamPrepareHeader(hStream, &ahd, 0)) m_error = 1;
- return ;
- }
- //resample defined in config
- // fucko: don't use compression settings if we're in a sep process, just generate raw wav
- // sep process isn't the best way, but we'll give it a shot
- if (!config_wav_convert)
- {
- m_acm_buf = NULL;
- m_acm_outbuf = NULL;
- }
- else
- {
- m_acm_buf = (unsigned char *)malloc(BUFSIZE);
- m_acm_outbuf = (unsigned char *)malloc(BUFSIZE);
- m_bytes_inbuf = 0;
- m_bytes_outbuf = 0;
- initWfx();
- m_convert_wfx = convert_wfx;
- m_wfx_src.wFormatTag = WAVE_FORMAT_PCM;
- m_wfx_src.nChannels = nch;
- m_wfx_src.nSamplesPerSec = srate;
- m_wfx_src.nAvgBytesPerSec = srate * nch * (bps >> 3);
- m_wfx_src.nBlockAlign = nch * (bps >> 3);
- m_wfx_src.wBitsPerSample = bps;
- m_wfx_src.cbSize = 0;
- MMRESULT rs = acmStreamOpen(&hStream, 0, &m_wfx_src, &m_convert_wfx.wfx, 0, 0, 0, ACM_STREAMOPENF_NONREALTIME);
- if (rs)
- {
- // need resampling
- WAVEFORMATEX wfx1;
- ZeroMemory(&wfx1, sizeof(wfx1));
- wfx1.wFormatTag = WAVE_FORMAT_PCM;
- if (acmFormatSuggest(0, &m_convert_wfx.wfx, &wfx1, sizeof(WAVEFORMATEX), ACM_FORMATSUGGESTF_WFORMATTAG)) m_error = 1;
- else if (acmStreamOpen(&hStream, 0, &wfx1, &m_convert_wfx.wfx, 0, 0, 0, ACM_STREAMOPENF_NONREALTIME)) m_error = 1;
- else if (acmStreamOpen(&hStreamResample, 0, &m_wfx_src, &wfx1, 0, 0, 0, ACM_STREAMOPENF_NONREALTIME)) m_error = 1;
- else
- {
- ZeroMemory(&ahdResample, sizeof(ahdResample));
- ahdResample.cbStruct = sizeof(ahdResample);
- ahdResample.pbSrc = m_acm_resample_buf = (unsigned char *)malloc(BUFSIZE);
- ahdResample.cbSrcLength = BUFSIZE;
- ahdResample.pbDst = m_acm_resample_outbuf = (unsigned char *)malloc(BUFSIZE);
- ahdResample.cbDstLength = BUFSIZE;
- if (acmStreamPrepareHeader(hStreamResample, &ahdResample, 0)) m_error = 1;
- m_bytes_inbuf_resample = 0;
- m_bytes_outbuf_resample = 0;
- }
- }
- if (!hStream)
- {
- m_error = 1;
- return ;
- }
- ZeroMemory(&ahd, sizeof(ahd));
- ahd.cbStruct = sizeof(ahd);
- ahd.pbSrc = m_acm_buf;
- ahd.cbSrcLength = BUFSIZE;
- ahd.pbDst = m_acm_outbuf;
- ahd.cbDstLength = BUFSIZE;
- if (acmStreamPrepareHeader(hStream, &ahd, 0)) m_error = 1;
- }
- }
- WavEncoder::~WavEncoder()
- {
- free(m_acm_buf);
- free(m_acm_outbuf);
- free(m_acm_resample_buf);
- free(m_acm_resample_outbuf);
- if (hStream)
- {
- if (ahd.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) acmStreamUnprepareHeader(hStream, &ahd, 0);
- acmStreamClose(hStream, 0);
- }
- if (hStreamResample)
- {
- if (ahdResample.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) acmStreamUnprepareHeader(hStreamResample, &ahdResample, 0);
- acmStreamClose(hStreamResample, 0);
- }
- }
- int WavEncoder::Encode(int framepos, void *in, int in_avail, int *in_used, void *out, int out_avail)
- {
- char *pin = (char *)in;
- char *pout = (char *)out;
- int retval = 0;
- if (!m_did_header && config_wav_do_header)
- {
- int s = 44;
- if (hStream)
- {
- s = 4 + 4 + 12 - 4;
- int t;
- if (m_convert_wfx.wfx.wFormatTag == WAVE_FORMAT_PCM) t = 0x10;
- else t = sizeof(WAVEFORMATEX) + m_convert_wfx.wfx.cbSize;
- s += 4 + t;
- if (s&1) s++;
- if (m_convert_wfx.wfx.wFormatTag != WAVE_FORMAT_PCM)
- s += 12;
- s += 8;
- }
- if (out_avail < s) return 0;
- //xx bytes of randomness
- m_hlen = s;
- m_did_header = 1;
- out_avail -= s;
- pout += s;
- retval = s;
- }
- if (!hStream)
- {
- //no ACM conversion
- int l = min(out_avail, in_avail);
- memcpy(pout, pin, l);
- *in_used = l;
- m_bytes_done += l;
- return l;
- }
- if (!m_bytes_outbuf)
- {
- if (hStreamResample)
- {
- if (!m_bytes_outbuf_resample)
- {
- DWORD flags = ACM_STREAMCONVERTF_BLOCKALIGN;
- int l = min(in_avail, BUFSIZE - m_bytes_inbuf_resample);
- if (l < 0) l = 0;
- if (l > 0) memcpy(m_acm_resample_buf + m_bytes_inbuf_resample, in, l);
- m_bytes_inbuf_resample += l;
- *in_used = l;
- m_nsam += l;
- ahdResample.cbSrcLength = m_bytes_inbuf_resample;
- acmStreamConvert(hStreamResample, &ahdResample, flags);
- m_bytes_inbuf_resample -= ahdResample.cbSrcLengthUsed;
- memcpy(m_acm_resample_buf, m_acm_resample_buf + ahdResample.cbSrcLengthUsed, m_bytes_inbuf_resample); //memmove
- m_bytes_outbuf_resample = ahdResample.cbDstLengthUsed;
- }
- in = (void*)m_acm_resample_outbuf;
- in_avail = m_bytes_outbuf_resample;
- m_bytes_outbuf_resample = 0;
- in_used = NULL;
- }
- DWORD flags = ACM_STREAMCONVERTF_BLOCKALIGN;
- int l = min(in_avail, BUFSIZE - m_bytes_inbuf);
- if (l < 0) l = 0;
- if (l > 0) memcpy(m_acm_buf + m_bytes_inbuf, in, l);
- m_bytes_inbuf += l;
- if (in_used)
- {
- *in_used = l;
- m_nsam += l;
- }
- if (m_bytes_inbuf)
- {
- ahd.cbSrcLength = m_bytes_inbuf;
- acmStreamConvert(hStream, &ahd, flags);
- m_bytes_inbuf -= ahd.cbSrcLengthUsed;
- memcpy(m_acm_buf, m_acm_buf + ahd.cbSrcLengthUsed, m_bytes_inbuf); //memmove
- m_bytes_outbuf = ahd.cbDstLengthUsed;
- m_bytes_done += l;
- }
- }
- if (m_bytes_outbuf)
- {
- int l = min(out_avail, m_bytes_outbuf);
- memcpy(pout, m_acm_outbuf, l);
- m_bytes_outbuf -= l;
- memcpy(m_acm_outbuf, m_acm_outbuf + l, m_bytes_outbuf);
- retval += l;
- }
- return retval;
- }
- void WavEncoder::FinishAudio(HANDLE fh, WavEncoder *coder)
- {
- if (!config_wav_do_header) return ;
- int len, i;
- const unsigned char ispred1[4] = {0x52 , 0x49 , 0x46 , 0x46 };
- const unsigned char ispred2[12] = {0x57, 0x41 , 0x56 , 0x45 , 0x66 , 0x6d , 0x74 , 0x20 , 0x10 , 0x0 , 0x0 , 0x0 };
- char c;
- int bps = coder->m_bps;
- int srate = coder->m_srate;
- int nch = coder->m_nch;
- len = coder->m_bytes_done;
- DWORD a;
- FileAlign(fh);
- SetFilePointer(fh, 0, 0, FILE_BEGIN);
- WriteFile(fh, ispred1, sizeof(ispred1), &a, NULL);
- i = len + (m_hlen) - 8;
- if (i&1) i++;
- WriteFile(fh, &i, 4, &a, NULL);
- WriteFile(fh, ispred2, sizeof(ispred2) - (hStream ? 4 : 0), &a, NULL);
- if (!hStream)
- {
- c = 1;
- WriteFile(fh, &c, 1, &a, NULL);
- c = 0;
- WriteFile(fh, &c, 1, &a, NULL);
- c = nch;
- WriteFile(fh, &c, 1, &a, NULL);
- c = 0;
- WriteFile(fh, &c, 1, &a, NULL);
- for (i = 0;i < 32;i += 8)
- {
- c = (srate >> i) & 0xff;
- WriteFile(fh, &c, 1, &a, NULL);
- }
- int tmp = srate * nch * (bps / 8);
- for (i = 0;i < 32;i += 8)
- {
- c = (tmp >> i) & 0xff;
- WriteFile(fh, &c, 1, &a, NULL);
- }
- tmp = (bps / 8) * nch;
- for (i = 0;i < 16;i += 8)
- {
- c = (tmp >> i) & 0xff;
- WriteFile(fh, &c, 1, &a, NULL);
- }
- c = bps;
- WriteFile(fh, &c, 1, &a, NULL);
- c = 0;
- WriteFile(fh, &c, 1, &a, NULL);
- const unsigned char iza[4] = {0x64 , 0x61 , 0x74 , 0x61};
- WriteFile(fh, iza, 4, &a, NULL);
- for (i = 0;i < 32;i += 8)
- {
- c = (len >> i) & 0xff;
- WriteFile(fh, &c, 1, &a, NULL);
- }
- }
- else
- {
- int t;
- if (m_convert_wfx.wfx.wFormatTag == WAVE_FORMAT_PCM) t = 0x10;
- else t = sizeof(WAVEFORMATEX) + m_convert_wfx.wfx.cbSize;
- WriteFile(fh, &t, 4, &a, 0);
- WriteFile(fh, &m_convert_wfx.wfx, t, &a, 0);
- FileAlign(fh);
- DWORD fact_ofs = 0;
- if (m_convert_wfx.wfx.wFormatTag != WAVE_FORMAT_PCM)
- {
- t = rev32('fact');
- WriteFile(fh, &t, 4, &a, 0);
- t = 4;
- WriteFile(fh, &t, 4, &a, 0);
- fact_ofs = FileTell(fh);
- SetFilePointer(fh, 4, 0, FILE_CURRENT);
- }
- t = rev32('data');
- WriteFile(fh, &t, 4, &a, 0);
- DWORD data_ofs = FileTell(fh);
- {
- DWORD t, bw;
- SetFilePointer(fh, 4, 0, FILE_BEGIN);
- t = GetFileSize(fh, 0) - 8;
- WriteFile(fh, &t, 4, &bw, 0);
- DWORD data_size = GetFileSize(fh, 0) - (data_ofs + 4);
- SetFilePointer(fh, data_ofs, 0, FILE_BEGIN);
- WriteFile(fh, &data_size, 4, &bw, 0);
- if (fact_ofs)
- {
- SetFilePointer(fh, fact_ofs, 0, FILE_BEGIN);
- t = coder->m_nsam / ((coder->m_bps >> 3) * coder->m_nch);
- WriteFile(fh, &t, 4, &bw, 0);
- }
- }
- }
- }
- int WavEncoder::GetLastError() { return m_error; }
|