add oversampler
This commit is contained in:
243
oversampling/WDL/audiobuffercontainer.cpp
Normal file
243
oversampling/WDL/audiobuffercontainer.cpp
Normal file
@@ -0,0 +1,243 @@
|
||||
#include "audiobuffercontainer.h"
|
||||
#include "queue.h"
|
||||
#include <assert.h>
|
||||
|
||||
void ChannelPinMapper::Reset()
|
||||
{
|
||||
for (int i=0; i < CHANNELPINMAPPER_MAXPINS; ++i)
|
||||
m_mapping[i].set_excl(i);
|
||||
}
|
||||
|
||||
void ChannelPinMapper::SetNPins(int nPins)
|
||||
{
|
||||
if (nPins<0) nPins=0;
|
||||
else if (nPins>CHANNELPINMAPPER_MAXPINS) nPins=CHANNELPINMAPPER_MAXPINS;
|
||||
int i;
|
||||
for (i = m_nPins; i < nPins; ++i)
|
||||
{
|
||||
ClearPin(i);
|
||||
if (i < m_nCh)
|
||||
{
|
||||
SetPin(i, i, true);
|
||||
}
|
||||
}
|
||||
m_nPins = nPins;
|
||||
}
|
||||
|
||||
void ChannelPinMapper::SetNChannels(int nCh, bool auto_passthru)
|
||||
{
|
||||
if (auto_passthru) for (int i = m_nCh; i < nCh && i < m_nPins; ++i) {
|
||||
SetPin(i, i, true);
|
||||
}
|
||||
m_nCh = nCh;
|
||||
}
|
||||
|
||||
void ChannelPinMapper::Init(const PinMapPin * pMapping, int nPins)
|
||||
{
|
||||
if (nPins<0) nPins=0;
|
||||
else if (nPins>CHANNELPINMAPPER_MAXPINS) nPins=CHANNELPINMAPPER_MAXPINS;
|
||||
memcpy(m_mapping, pMapping, nPins*sizeof(PinMapPin));
|
||||
memset(m_mapping+nPins, 0, (CHANNELPINMAPPER_MAXPINS-nPins)*sizeof(PinMapPin));
|
||||
m_nPins = m_nCh = nPins;
|
||||
}
|
||||
|
||||
#define BITMASK64(bitIdx) (((WDL_UINT64)1)<<(bitIdx))
|
||||
|
||||
void ChannelPinMapper::ClearPin(int pinIdx)
|
||||
{
|
||||
if (pinIdx >=0 && pinIdx < CHANNELPINMAPPER_MAXPINS) m_mapping[pinIdx].clear();
|
||||
}
|
||||
|
||||
void ChannelPinMapper::SetPin(int pinIdx, int chIdx, bool on)
|
||||
{
|
||||
if (pinIdx >=0 && pinIdx < CHANNELPINMAPPER_MAXPINS)
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
m_mapping[pinIdx].set_chan(chIdx);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_mapping[pinIdx].clear_chan(chIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ChannelPinMapper::TogglePin(int pinIdx, int chIdx)
|
||||
{
|
||||
bool on = GetPin(pinIdx, chIdx);
|
||||
on = !on;
|
||||
SetPin(pinIdx, chIdx, on);
|
||||
return on;
|
||||
}
|
||||
|
||||
bool ChannelPinMapper::GetPin(int pinIdx, int chIdx) const
|
||||
{
|
||||
if (pinIdx >= 0 && pinIdx < CHANNELPINMAPPER_MAXPINS)
|
||||
{
|
||||
return m_mapping[pinIdx].has_chan(chIdx);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ChannelPinMapper::IsStraightPassthrough() const
|
||||
{
|
||||
if (m_nCh != m_nPins) return false;
|
||||
PinMapPin tmp;
|
||||
tmp.clear();
|
||||
for (int i = 0; i < m_nPins; ++i)
|
||||
{
|
||||
tmp.set_chan(i);
|
||||
if (!tmp.equal_to(m_mapping[i])) return false;
|
||||
tmp.clear_chan(i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define PINMAPPER_MAGIC 1000
|
||||
|
||||
const char *ChannelPinMapper::SaveStateNew(int* pLen)
|
||||
{
|
||||
m_cfgret.Clear();
|
||||
int magic = PINMAPPER_MAGIC;
|
||||
WDL_Queue__AddToLE(&m_cfgret, &magic);
|
||||
WDL_Queue__AddToLE(&m_cfgret, &m_nCh);
|
||||
WDL_Queue__AddToLE(&m_cfgret, &m_nPins);
|
||||
const int num64 = wdl_max(1,(wdl_min(m_nCh,CHANNELPINMAPPER_MAXPINS) + 63)/64);
|
||||
for (int y = 0; y < num64; y ++)
|
||||
{
|
||||
for (int x = 0; x < m_nPins; x ++)
|
||||
{
|
||||
const WDL_UINT64 v = m_mapping[x].get_64(y);
|
||||
WDL_Queue__AddToLE(&m_cfgret, &v);
|
||||
}
|
||||
}
|
||||
*pLen = m_cfgret.GetSize();
|
||||
return (const char*)m_cfgret.Get();
|
||||
}
|
||||
|
||||
bool ChannelPinMapper::LoadState(const char* buf, int len)
|
||||
{
|
||||
WDL_Queue chunk;
|
||||
chunk.Add(buf, len);
|
||||
int* pMagic = WDL_Queue__GetTFromLE(&chunk, (int*)0);
|
||||
if (!pMagic || *pMagic != PINMAPPER_MAGIC) return false;
|
||||
int* pNCh = WDL_Queue__GetTFromLE(&chunk, (int*) 0);
|
||||
int* pNPins = WDL_Queue__GetTFromLE(&chunk, (int*) 0);
|
||||
if (!pNCh || !pNPins) return false;
|
||||
const int src_pins = *pNPins;
|
||||
SetNPins(src_pins);
|
||||
SetNChannels(*pNCh);
|
||||
const int num64 = wdl_max(1,(wdl_min(m_nCh,CHANNELPINMAPPER_MAXPINS)+63)/64);
|
||||
const int maplen = src_pins * sizeof(WDL_UINT64);
|
||||
for (int y = 0; y < num64; y ++)
|
||||
{
|
||||
if (chunk.Available() < maplen) return y>0;
|
||||
const WDL_UINT64 *pMap = (const WDL_UINT64 *)WDL_Queue__GetDataFromLE(&chunk, maplen, sizeof(WDL_UINT64));
|
||||
const int sz = wdl_min(m_nPins,src_pins);
|
||||
for (int x = 0; x < sz; x ++)
|
||||
{
|
||||
m_mapping[x].set_64(pMap[x], y);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
AudioBufferContainer::AudioBufferContainer()
|
||||
{
|
||||
m_nCh = 0;
|
||||
m_nFrames = 0;
|
||||
m_fmt = FMT_32FP;
|
||||
m_interleaved = true;
|
||||
m_hasData = false;
|
||||
}
|
||||
|
||||
// converts interleaved buffer to interleaved buffer, using min(len_in,len_out) and zeroing any extra samples
|
||||
// isInput means it reads from track channels and writes to plugin pins
|
||||
// wantZeroExcessOutput=false means that untouched channels will be preserved in buf_out
|
||||
void PinMapperConvertBuffers(const double *buf, int len_in, int nch_in,
|
||||
double *buf_out, int len_out, int nch_out,
|
||||
const ChannelPinMapper *pinmap, bool isInput, bool wantZeroExcessOutput)
|
||||
{
|
||||
|
||||
if (pinmap->IsStraightPassthrough() || !pinmap->GetNPins())
|
||||
{
|
||||
int x;
|
||||
char *op = (char *)buf_out;
|
||||
const char *ip = (const char *)buf;
|
||||
|
||||
const int ip_adv = nch_in * sizeof(double);
|
||||
|
||||
const int clen = wdl_min(nch_in, nch_out) * sizeof(double);
|
||||
const int zlen = nch_out > nch_in ? (nch_out - nch_in) * sizeof(double) : 0;
|
||||
|
||||
const int cplen = wdl_min(len_in,len_out);
|
||||
|
||||
for (x=0;x<cplen;x++)
|
||||
{
|
||||
memcpy(op,ip,clen);
|
||||
op += clen;
|
||||
if (zlen)
|
||||
{
|
||||
if (wantZeroExcessOutput) memset(op,0,zlen);
|
||||
op += zlen;
|
||||
}
|
||||
ip += ip_adv;
|
||||
}
|
||||
if (x < len_out && wantZeroExcessOutput) memset(op, 0, (len_out-x)*sizeof(double)*nch_out);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wantZeroExcessOutput) memset(buf_out,0,len_out*nch_out*sizeof(double));
|
||||
|
||||
const int npins = wdl_min(pinmap->GetNPins(),isInput ? nch_out : nch_in);
|
||||
const int nchan = isInput ? nch_in : nch_out;
|
||||
|
||||
int p;
|
||||
PinMapPin clearmask;
|
||||
clearmask.clear();
|
||||
for (p = 0; p < npins; p ++)
|
||||
{
|
||||
const PinMapPin &map = pinmap->m_mapping[p];
|
||||
for (unsigned int x = 0; map.enum_chans(&x,nchan); x ++)
|
||||
{
|
||||
int i=len_in;
|
||||
const double *ip = buf + (isInput ? x : p);
|
||||
const int out_idx = (isInput ? p : x);
|
||||
|
||||
bool want_zero=false;
|
||||
if (!wantZeroExcessOutput)
|
||||
{
|
||||
if (!clearmask.has_chan(out_idx))
|
||||
{
|
||||
clearmask.set_chan(out_idx);
|
||||
want_zero=true;
|
||||
}
|
||||
}
|
||||
|
||||
double *op = buf_out + out_idx;
|
||||
|
||||
if (want_zero)
|
||||
{
|
||||
while (i-- > 0)
|
||||
{
|
||||
*op = *ip;
|
||||
op += nch_out;
|
||||
ip += nch_in;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (i-- > 0)
|
||||
{
|
||||
*op += *ip;
|
||||
op += nch_out;
|
||||
ip += nch_in;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user