kopia lustrzana https://github.com/backface/turtlestitch
new "play sound at sample rate" command primitive
rodzic
6b874c18f3
commit
1c9532edc3
|
@ -17,6 +17,7 @@
|
|||
* new sound + music "volume" feature + blocks
|
||||
* new sound + music stereo "panning" feature + blocks
|
||||
* new sound attribute getter reporter
|
||||
* new "play sound at sample rate" command
|
||||
* new "play frequency" commands in the Sounds category
|
||||
* added "neg" selector to monadic function reporter in "Operators" category
|
||||
* added "log2" selector to monadic function reporter in "Operators" category
|
||||
|
@ -60,6 +61,7 @@
|
|||
|
||||
### 2019-04-08
|
||||
* Blocks, Objects, Threads: new "getSoundAttribute" reporter primitive
|
||||
* Blocks, Objects, Threads: new "play sound at sample rate" command primitive
|
||||
|
||||
### 2019-04-05
|
||||
* Objects: eliminated "clicks" when playing music notes
|
||||
|
|
|
@ -1010,6 +1010,19 @@ SyntaxElementMorph.prototype.labelPart = function (spec) {
|
|||
true // read-only
|
||||
);
|
||||
break;
|
||||
case '%rate':
|
||||
part = new InputSlotMorph(
|
||||
null,
|
||||
true,
|
||||
{
|
||||
'22.05 kHz' : 22050,
|
||||
'44.1 kHz' : 44100,
|
||||
'88.2 kHz' : 88200,
|
||||
'96 kHz' : 96000
|
||||
}
|
||||
);
|
||||
part.setContents(1);
|
||||
break;
|
||||
case '%month':
|
||||
part = new InputSlotMorph(
|
||||
null, // text
|
||||
|
|
|
@ -434,6 +434,12 @@ SpriteMorph.prototype.initBlocks = function () {
|
|||
category: 'sound',
|
||||
spec: 'play sound %snd until done'
|
||||
},
|
||||
doPlaySoundAtRate: {
|
||||
type: 'command',
|
||||
category: 'sound',
|
||||
spec: 'play sound %snd at %rate hz',
|
||||
defaults: ['', 44100]
|
||||
},
|
||||
doStopAllSounds: {
|
||||
type: 'command',
|
||||
category: 'sound',
|
||||
|
@ -2035,6 +2041,7 @@ SpriteMorph.prototype.blockTemplates = function (category) {
|
|||
blocks.push(block('doPlaySoundUntilDone'));
|
||||
blocks.push(block('doStopAllSounds'));
|
||||
blocks.push('-');
|
||||
blocks.push(block('doPlaySoundAtRate'));
|
||||
blocks.push(block('reportGetSoundAttribute'));
|
||||
blocks.push('-');
|
||||
blocks.push(block('doRest'));
|
||||
|
@ -7517,6 +7524,7 @@ StageMorph.prototype.blockTemplates = function (category) {
|
|||
blocks.push(block('doPlaySoundUntilDone'));
|
||||
blocks.push(block('doStopAllSounds'));
|
||||
blocks.push('-');
|
||||
blocks.push(block('doPlaySoundAtRate'));
|
||||
blocks.push(block('reportGetSoundAttribute'));
|
||||
blocks.push('-');
|
||||
blocks.push(block('doRest'));
|
||||
|
|
|
@ -2249,6 +2249,71 @@ Process.prototype.doStopAllSounds = function () {
|
|||
}
|
||||
};
|
||||
|
||||
Process.prototype.doPlaySoundAtRate = function (name, rate) {
|
||||
var sound, samples, ctx, gain, pan, channels, frameCount, arrayBuffer,
|
||||
i, source, rcvr;
|
||||
|
||||
if (!(name instanceof List)) {
|
||||
sound = name instanceof Sound ? name : detect(
|
||||
this.blockReceiver().sounds.asArray(),
|
||||
function (s) {return s.name === name.toString(); }
|
||||
);
|
||||
if (!sound.audioBuffer) {
|
||||
this.decodeSound(sound);
|
||||
return;
|
||||
}
|
||||
samples = this.reportGetSoundAttribute('samples', sound);
|
||||
} else {
|
||||
samples = name;
|
||||
}
|
||||
|
||||
rcvr = this.blockReceiver();
|
||||
ctx = rcvr.audioContext();
|
||||
gain = rcvr.getGainNode();
|
||||
pan = rcvr.getPannerNode();
|
||||
channels = (samples.at(1) instanceof List) ? samples.length() : 1;
|
||||
frameCount = (channels === 1) ? samples.length() : samples.at(1).length();
|
||||
arrayBuffer = ctx.createBuffer(channels, frameCount, +rate || 44100);
|
||||
|
||||
if (!arrayBuffer.copyToChannel) {
|
||||
arrayBuffer.copyToChannel = function (src, channel) {
|
||||
var buffer = this.getChannelData(channel);
|
||||
for (i = 0; i < src.length; i += 1) {
|
||||
buffer[i] = src[i];
|
||||
}
|
||||
};
|
||||
}
|
||||
if (channels === 1) {
|
||||
arrayBuffer.copyToChannel(
|
||||
Float32Array.from(samples.asArray()),
|
||||
0,
|
||||
0
|
||||
);
|
||||
} else {
|
||||
for (i = 0; i < channels; i += 1) {
|
||||
arrayBuffer.copyToChannel(
|
||||
Float32Array.from(samples.at(i + 1).asArray()),
|
||||
i,
|
||||
0
|
||||
);
|
||||
}
|
||||
}
|
||||
source = ctx.createBufferSource();
|
||||
source.buffer = arrayBuffer;
|
||||
rcvr.setVolume(rcvr.volume);
|
||||
source.connect(gain);
|
||||
if (pan) {
|
||||
gain.connect(pan);
|
||||
pan.connect(ctx.destination);
|
||||
rcvr.setPan(rcvr.pan);
|
||||
} else {
|
||||
gain.connect(ctx.destination);
|
||||
}
|
||||
source.start();
|
||||
source.pause = source.stop;
|
||||
rcvr.parentThatIsA(StageMorph).activeSounds.push(source);
|
||||
};
|
||||
|
||||
Process.prototype.reportGetSoundAttribute = function (choice, soundName) {
|
||||
var sound = soundName instanceof Sound ? soundName : detect(
|
||||
this.blockReceiver().sounds.asArray(),
|
||||
|
|
Ładowanie…
Reference in New Issue