Skip to content

Commit

Permalink
Add a count-in option (#432)
Browse files Browse the repository at this point in the history
* WIP count in

* Final corretions on count-in

* Fixed builds and extend jQuery API
  • Loading branch information
Danielku15 authored Nov 27, 2020
1 parent 9f1c4e9 commit d9b8a45
Show file tree
Hide file tree
Showing 12 changed files with 201 additions and 24 deletions.
3 changes: 3 additions & 0 deletions playground-template/control-template.html
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@
</div>

<div class="at-player-right">
<a href="#" class="at-count-in disabled" data-toggle="tooltip" data-placement="top" title="Count-In">
<i class="fas fa-hourglass-half"></i>
</a>
<a href="#" class="at-metronome disabled" data-toggle="tooltip" data-placement="top" title="Metronome">
<i class="fas fa-edit"></i>
</a>
Expand Down
11 changes: 11 additions & 0 deletions playground-template/control.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,17 @@ function setupControl(selector) {
}
};

control.querySelector('.at-count-in').onclick = function (e) {
e.stopPropagation();
const link = e.target.closest('a');
link.classList.toggle('active');
if (link.classList.contains('active')) {
at.countInVolume = 1;
} else {
at.countInVolume = 0;
}
};

control.querySelectorAll('.at-speed-options a').forEach(function (a) {
a.onclick = function (e) {
e.preventDefault();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ public double MasterVolume
set => DispatchOnWorkerThread(() => { Player.MasterVolume = value; });
}

public double CountInVolume
{
get => Player.CountInVolume;
set => DispatchOnWorkerThread(() => { Player.CountInVolume = value; });
}

public double MetronomeVolume
{
get => Player.MetronomeVolume;
Expand Down
13 changes: 13 additions & 0 deletions src/AlphaTabApiBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,19 @@ export class AlphaTabApiBase<TSettings> {
}
}

public get countInVolume(): number {
if (!this.player) {
return 0;
}
return this.player.countInVolume;
}

public set countInVolume(value: number) {
if (this.player) {
this.player.countInVolume = value;
}
}

public get tickPosition(): number {
if (!this.player) {
return 0;
Expand Down
7 changes: 6 additions & 1 deletion src/platform/javascript/AlphaSynthWebAudioOutput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,16 @@ export class AlphaSynthWebAudioOutput implements ISynthOutput {
}
}

private _outputBuffer:Float32Array = new Float32Array(0);
private generateSound(e: AudioProcessingEvent): void {
let left: Float32Array = e.outputBuffer.getChannelData(0);
let right: Float32Array = e.outputBuffer.getChannelData(1);
let samples: number = left.length + right.length;
let buffer: Float32Array = new Float32Array(samples);
let buffer = this._outputBuffer;
if(buffer.length != samples) {
buffer = new Float32Array(samples);
this._outputBuffer = buffer;
}
this._circularBuffer.read(buffer, 0, Math.min(buffer.length, this._circularBuffer.count));
let s: number = 0;
for (let i: number = 0; i < left.length; i++) {
Expand Down
3 changes: 3 additions & 0 deletions src/platform/javascript/AlphaSynthWebWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ export class AlphaSynthWebWorker {
case 'alphaSynth.setIsLooping':
this._player.isLooping = data.value;
break;
case 'alphaSynth.setCountInVolume':
this._player.countInVolume = data.value;
break;
case 'alphaSynth.play':
this._player.play();
break;
Expand Down
13 changes: 13 additions & 0 deletions src/platform/javascript/AlphaSynthWebWorkerApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export class AlphaSynthWebWorkerApi implements IAlphaSynth {
private _state: PlayerState = PlayerState.Paused;
private _masterVolume: number = 0;
private _metronomeVolume: number = 0;
private _countInVolume: number = 0;
private _playbackSpeed: number = 0;
private _tickPosition: number = 0;
private _timePosition: number = 0;
Expand Down Expand Up @@ -82,6 +83,18 @@ export class AlphaSynthWebWorkerApi implements IAlphaSynth {
value: value
});
}
public get countInVolume(): number {
return this._countInVolume;
}

public set countInVolume(value: number) {
value = SynthHelper.clamp(value, SynthConstants.MinVolume, SynthConstants.MaxVolume);
this._countInVolume = value;
this._synth.postMessage({
cmd: 'alphaSynth.setCountInVolume',
value: value
});
}

public get playbackSpeed(): number {
return this._playbackSpeed;
Expand Down
7 changes: 7 additions & 0 deletions src/platform/javascript/JQueryAlphaTab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,13 @@ export class JQueryAlphaTab {
return context.metronomeVolume;
}

public countInVolume(element: jQuery, context: AlphaTabApi, countInVolume?: number): number {
if (typeof countInVolume === 'number') {
context.countInVolume = countInVolume;
}
return context.countInVolume;
}

public playbackSpeed(element: jQuery, context: AlphaTabApi, playbackSpeed?: number): number {
if (typeof playbackSpeed === 'number') {
context.playbackSpeed = playbackSpeed;
Expand Down
46 changes: 35 additions & 11 deletions src/synth/AlphaSynth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export class AlphaSynth implements IAlphaSynth {
private _tickPosition: number = 0;
private _timePosition: number = 0;
private _metronomeVolume: number = 0;
private _countInVolume: number = 0;

/**
* Gets the {@link ISynthOutput} used for playing the generated samples.
Expand Down Expand Up @@ -68,6 +69,15 @@ export class AlphaSynth implements IAlphaSynth {
this._synthesizer.metronomeVolume = value;
}

public get countInVolume(): number {
return this._countInVolume;
}

public set countInVolume(value: number) {
value = SynthHelper.clamp(value, SynthConstants.MinVolume, SynthConstants.MaxVolume);
this._countInVolume = value;
}

public get playbackSpeed(): number {
return this._sequencer.playbackSpeed;
}
Expand Down Expand Up @@ -182,14 +192,27 @@ export class AlphaSynth implements IAlphaSynth {
return false;
}
this.output.activate();
this._synthesizer.setupMetronomeChannel(this.metronomeVolume);

this.playInternal();

if (this._countInVolume > 0) {
Logger.debug('AlphaSynth', 'Starting countin');
this._sequencer.startCountIn();
this._synthesizer.setupMetronomeChannel(this._countInVolume);
this.tickPosition = 0;
}

this.output.play();
return true;
}

private playInternal() {
Logger.debug('AlphaSynth', 'Starting playback');
this._synthesizer.setupMetronomeChannel(this.metronomeVolume);
this.state = PlayerState.Playing;
(this.stateChanged as EventEmitterOfT<PlayerStateChangedEventArgs>).trigger(
new PlayerStateChangedEventArgs(this.state, false)
);
this.output.play();
return true;
}

public pause(): void {
Expand Down Expand Up @@ -227,20 +250,17 @@ export class AlphaSynth implements IAlphaSynth {
new PlayerStateChangedEventArgs(this.state, true)
);
}

public playOneTimeMidiFile(midi: MidiFile): void {
// pause current playback.
this.pause();

this._sequencer.loadOneTimeMidi(midi);

this._sequencer.stop();
this._synthesizer.noteOffAll(true);
this.tickPosition = 0;

(this.stateChanged as EventEmitterOfT<PlayerStateChangedEventArgs>).trigger(
new PlayerStateChangedEventArgs(this.state, false)
);
this.output.play();
}

Expand Down Expand Up @@ -335,7 +355,11 @@ export class AlphaSynth implements IAlphaSynth {

if (this._tickPosition >= endTick) {
Logger.debug('AlphaSynth', 'Finished playback');
if(this._sequencer.isPlayingOneTimeMidi) {
if (this._sequencer.isPlayingCountIn) {
this._sequencer.resetCountIn();
this.timePosition = this._sequencer.currentTime;
this.playInternal()
} else if (this._sequencer.isPlayingOneTimeMidi) {
this._sequencer.resetOneTimeMidi();
this.state = PlayerState.Paused;
this.output.pause();
Expand All @@ -359,7 +383,7 @@ export class AlphaSynth implements IAlphaSynth {
const endTime: number = this._sequencer.endTime;
const endTick: number = this._sequencer.endTick;

if(!this._sequencer.isPlayingOneTimeMidi) {
if (!this._sequencer.isPlayingOneTimeMidi && !this._sequencer.isPlayingCountIn) {
Logger.debug(
'AlphaSynth',
`Position changed: (time: ${currentTime}/${endTime}, tick: ${currentTick}/${endTick}, Active Voices: ${this._synthesizer.activeVoiceCount}`
Expand Down
7 changes: 6 additions & 1 deletion src/synth/IAlphaSynth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ export interface IAlphaSynth {
*/
isLooping: boolean;

/**
* Gets or sets volume of the metronome during count-in. (range: 0.0-3.0, default 0.0 - no count in)
*/
countInVolume: number;

/**
* Destroys the synthesizer and all related components
*/
Expand All @@ -91,7 +96,7 @@ export interface IAlphaSynth {
* Stopps the playback
*/
stop(): void;

/**
* Stops any ongoing playback and plays the given midi file instead.
* @param midi The midi file to play
Expand Down
Loading

0 comments on commit d9b8a45

Please sign in to comment.