Warning: session_start(): open(/var/lib/php/sessions/sess_i262v4g13sbpb34tb9g04tqho1, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
!7
import static x30_pkg.x30_util.VF1;
import javax.sound.sampled.AudioFormat;
cmodule APlayAudioOutput > DynPrintLog {
switchable int bufSizeMS = 200;
switchable int sampleRate = 44100;
switchable int channels = 2; // only 2 is tested
switchable int bits = 16;
switchable float gain = 1;
switchable bool registerService;
transient L> sources = notifyingList(r setNumSources);
transient SimpleLiveValue numSources = new(Int, 0);
transient StreamSoundToAPlay loop;
transient int bufSizeInFrames;
transient short[] buffer;
visualize {
ret centerAndSouth(super.visualize(),
withLeftAndRightMargin(vstackWithSpacing(
withLabel("Volume (0-200%):", liveSliderZeroToOne(gain/2, voidfunc(float f) { setField(gain := f*2) })),
jrightalignedline(withLabel("Sound sources:", jLiveValueLabel(numSources)))
)));
}
start {
ownResource(loop = new StreamSoundToAPlay);
copyFields(module(), loop, 'sampleRate, 'channels, 'bits, 'bufSizeMS);
bufSizeInFrames = msToSamples_int(bufSizeMS, sampleRate);
buffer = new short[bufSizeInFrames*2];
fillBuffer();
loop.start();
loop.writeSamples(buffer);
doEveryAndNow(bufSizeMS, r {
fillBuffer();
loop.writeSamples(buffer);
});
dm_registerAs audioOutputModule();
if (registerService)
dm_registerService('playWAVAndWait, func(S method, O[] args) -> bool {
temp enter();
callMC(f dm_playWAV, args);
true;
});
}
void fillBuffer enter {
VF1> vfRemoveSource = voidfunc(VF1 source) {
removeSource(source)
};
double[] pair = new double[2];
for i over buffer: {
audio_makeSampleFromSources(sources, pair, gain, vfRemoveSource);
buffer[i++] = clipShort(pair[0]);
buffer[i] = clipShort(pair[1]);
}
}
void setNumSources { numSources.set(l(sources)); }
// hold audio sources during reload
O _getReloadData() { ret sources; }
void _setReloadData(L> sources) { addAll(this.sources, sources); }
// API
void addSource(VF1 source) {
sources.add(source);
print("Audio source added.");
}
void removeSource(VF1 source) {
sources.remove(source);
print("Audio source removed.");
}
AudioFormat getAudioFormat() { ret new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, sampleRate, bits, channels, channels*bits/2, sampleRate, false); }
long samplesPlayed() { ret loop.frameCounter; }
}