top of page

upmix work flow for eigenmike with compass upmixer with ATK:

///////////////Step 1 - prepare for Xover////////////////
(
~egPath = "/Volumes/Project_WeiYang/eigenmic/01_1.wav";
// ~egPath = "/Volumes/Project_WeiYang/upmixer_test/click_test/0_click_precompass/click_HOA4_phi90.wav";
~egBuffer = CtkBuffer(~egPath).load;
~size = 8192; ~sampleRate = 48000;
~freqs = [ 400, 1000, 1800];  //eigenMic crossover freqs
~alpha = 2.5;
~sampleRate = 48000;
~duration = ~egBuffer.duration;
)

(
~banks= Signal.gaussianBank(~size, ~freqs, ~alpha, ~sampleRate);
~kernels = [];
~banks.do{arg bank;
   // ~kernels = ~kernels.add(CtkBuffer.collection(bank, 1, s).load); // for realtime only...
   ~kernels = ~kernels.add(CtkBuffer.collection(bank, 1, s));
};
)

(
//////////////////////Step 2 - crossover the eigenmike recording //////////////////////
~egXover = CtkSynthDef(\egXover, {arg outBus=0, egBuffer, kernel;
   var size = 8192;
   var sourceDist = 0.3;
   // var egSig, egFiltSig1, egFiltSig2, egFiltSig3, egFiltSig4;
   var egSig, egFiltSig;
   var egOrder = 4;

    egSig = PlayBuf.ar(egOrder.asHoaOrder.size, egBuffer, BufRateScale.kr(egBuffer), doneAction: 2); //import eigenmike recording in HOA4
   egSig = HoaNFDist.ar(egSig, egOrder);  //ATK Hoa
   egSig = HoaNFCtrl.ar(egSig, AtkHoa.refRadius, sourceDist, egOrder);//move to recording distance

    egFiltSig = Convolution2.ar(egSig, kernel, 0, size);
   Out.ar(outBus, egFiltSig);
})
)

(
~kernels.do{arg thisKernel, i;
   var score, outputPath;
   score = CtkScore.new;
   score.add(~egBuffer);
   score.add(thisKernel);
   outputPath =  "/Volumes/Project_WeiYang/upmixer_test/egFiltSND/"++ i.asString ++ "_hoa4.wav";//set destination for Xover-ed signals

    score.add(
       ~egXover.note(starttime: 0.0, duration: ~duration).kernel_(thisKernel).egBuffer_(~egBuffer)
   );

    score.write(
       outputPath.standardizePath,
       duration: ~duration,
       sampleRate: ~sampleRate,
       sampleFormat: 'float',
       headerFormat: 'WAV',
       options: ServerOptions.new.numOutputBusChannels_(25).memSize_(2.pow(21))
   )
}
)

/*Step 3 - UpMix with Compass UpMixer within Reaper (https://leomccormack.github.io/sparta-site/docs/plugins/compass-suite/):
set the following prameters for each Xover-ed audio files
                     input order -> output order
0.wav:                  1                           5
1.wav:                   2                          5
2.wav:                  3                          5
3.wav:                  4                          5
Format: ACN N3D
*/

/////////////// Step 4 - prepare for UpMixing////////////////
(
~egFiltFolderPath = "/Volumes/Project_WeiYang/upmixer_test/egFiltSND/".standardizePath;
~compFolderPath = "/Volumes/Project_WeiYang/upmixer_test/compass_upmixed/".standardizePath;
~egFiltBufs = []; ~compBufs = []; 

PathName(~egFiltFolderPath).filesDo{arg pathname;
   var egFiltPath =pathname.fullPath;
   egFiltPath.postln;
   ~egFiltBufs = ~egFiltBufs.add(CtkBuffer.diskin(egFiltPath, size: 2.pow(21)).load) //sufficient size!
};

PathName(~compFolderPath).filesDo{arg pathname;
   var compPath =pathname.fullPath;
   compPath.postln;
   ~compBufs = ~compBufs.add(CtkBuffer.diskin(compPath, size: 2.pow(21)).load)  //sufficient size!
};
)

////////////////////Step 5 - replace channels of the compass upmixed signal with the original recording information//////////////////////
(
~upmix = CtkSynthDef(\upmixTest, {
   |gain = 0.0, egFiltBufs = #[0, 1, 2, 3], compBufs = #[0, 1, 2, 3], normGains= #[0, 1, 2, 3], numSampsDels = #[0, 1, 2, 3]|
   var egFiltSigs, compSigs, upSigs, out, sourceDist = 0.3, targetOrder = 5;

    //import Xover-ed eigenMike signals and apply delay correction
   egFiltSigs = egFiltBufs.collect{|egFiltBuf, i|
       var egFiltSig;
       egFiltSig = DiskIn.ar(25, egFiltBuf);
       egFiltSig = DelayN.ar(egFiltSig, delaytime: numSampsDels.at(i) * SampleDur.ir)
   };

    //compass-upmixed signal and apply gain correction;
   compSigs = compBufs.collect{|compBuf, i|
       var compSig;
       compSig = DiskIn.ar(36, compBuf);
       compSig = HoaNFDist.ar(compSig * normGains.at(i).dbamp, targetOrder);
   };

    //discard & replace
   upSigs = egFiltSigs.size.collect({ |i|
       egFiltSigs.at(i).keep((i + 1).asHoaOrder.size) ++ compSigs.at(i).drop((i + 1).asHoaOrder.size)
   }).sum;

    // move back to atk ref dist
   out = HoaNFCtrl.ar(upSigs,  sourceDist, AtkHoa.refRadius, targetOrder);//move from recording distance back to ref dist
   Out.ar(0, out * gain.dbamp);
});
)

////////////////////Step 6 - Render!!//////////////////////
(
~finalOutputPath = "/Volumes/Project_WeiYang/upmixer_test/final_upmixed/final.wav"; //set the final output destination
~normGains = [0, 0, 0, 0];  //compass
~numSampsDels = [0, 0, 0, 0]; //compas
~score = CtkScore.new;
~score.add(~egFiltBufs);
~score.add(~compBufs);
~sampleRate = 48000;
~duration = ~egFiltBufs[0].duration;

~score.add(
   ~upmix.note(starttime: 0.0, duration: ~duration).gain_(-12.0)
   .egFiltBufs_(~egFiltBufs).compBufs_(~diracBufs)
   .normGains_(~normGains).numSampsDels_(~numSampsDels)
);

~score.write(
   ~finalOutputPath.standardizePath,
   duration: ~duration, //why does it add 2'' w/o this?
   sampleRate: ~sampleRate,
   sampleFormat: 'float',
   headerFormat: 'WAV',
   options: ServerOptions.new.numOutputBusChannels_(36).memSize_(2.pow(21))//
)
)

bottom of page