#include "audiobuffercontainer.h" #include "queue.h" #include 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;xGetNPins(),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; } } } } } }