Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework state handling of one-time-midi #787

Merged
merged 6 commits into from
Mar 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src.csharp/AlphaTab.Windows/NAudioSynthOutput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,14 @@ private void RequestBuffers()
public override int Read(float[] buffer, int offset, int count)
{
var read = new Float32Array(count);
_circularBuffer.Read(read, 0, System.Math.Min(read.Length, _circularBuffer.Count));

var samplesFromBuffer = _circularBuffer.Read(read, 0, System.Math.Min(read.Length, _circularBuffer.Count));

Buffer.BlockCopy(read.Data, 0, buffer, offset * sizeof(float),
count * sizeof(float));

var samples = count / 2;
((EventEmitterOfT<double>) SamplesPlayed).Trigger(samples);
((EventEmitterOfT<double>) SamplesPlayed).Trigger(samples / SynthConstants.AudioChannels);

RequestBuffers();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ internal class AndroidAudioWorker(
private fun writeSamples() {
while (!_stopped) {
if (_track.playState == AudioTrack.PLAYSTATE_PLAYING) {
_output.read(_buffer, 0, _buffer.size)
val samplesFromBuffer = _output.read(_buffer, 0, _buffer.size)
if (_previousPosition == -1) {
_previousPosition = _track.playbackHeadPosition
_track.getTimestamp(_timestamp)
}
_track.write(_buffer, 0, _buffer.size, AudioTrack.WRITE_BLOCKING)
_track.write(_buffer, 0, samplesFromBuffer, AudioTrack.WRITE_BLOCKING)
} else {
_playingSemaphore.acquire() // wait for playing to start
_playingSemaphore.release() // release semaphore for others
Expand Down
62 changes: 61 additions & 1 deletion src/AlphaTabApiBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -994,7 +994,7 @@ export class AlphaTabApiBase<TSettings> {
if (
nextBeatBoundings &&
nextBeatBoundings.barBounds.masterBarBounds.staveGroupBounds ===
barBoundings.staveGroupBounds
barBoundings.staveGroupBounds
) {
nextBeatX = nextBeatBoundings.visualBounds.x;
}
Expand Down Expand Up @@ -1032,13 +1032,18 @@ export class AlphaTabApiBase<TSettings> {
}

private _beatMouseDown: boolean = false;
private _noteMouseDown: boolean = false;
private _selectionStart: SelectionInfo | null = null;
private _selectionEnd: SelectionInfo | null = null;

public beatMouseDown: IEventEmitterOfT<Beat> = new EventEmitterOfT<Beat>();
public beatMouseMove: IEventEmitterOfT<Beat> = new EventEmitterOfT<Beat>();
public beatMouseUp: IEventEmitterOfT<Beat | null> = new EventEmitterOfT<Beat | null>();

public noteMouseDown: IEventEmitterOfT<Note> = new EventEmitterOfT<Note>();
public noteMouseMove: IEventEmitterOfT<Note> = new EventEmitterOfT<Note>();
public noteMouseUp: IEventEmitterOfT<Note | null> = new EventEmitterOfT<Note | null>();

private onBeatMouseDown(originalEvent: IMouseEventArgs, beat: Beat): void {
if (this._isDestroyed) {
return;
Expand All @@ -1057,6 +1062,16 @@ export class AlphaTabApiBase<TSettings> {
this.uiFacade.triggerEvent(this.container, 'beatMouseDown', beat, originalEvent);
}

private onNoteMouseDown(originalEvent: IMouseEventArgs, note: Note): void {
if (this._isDestroyed) {
return;
}

this._noteMouseDown = true;
(this.noteMouseDown as EventEmitterOfT<Note>).trigger(note);
this.uiFacade.triggerEvent(this.container, 'noteMouseDown', note, originalEvent);
}

private onBeatMouseMove(originalEvent: IMouseEventArgs, beat: Beat): void {
if (this._isDestroyed) {
return;
Expand All @@ -1072,6 +1087,15 @@ export class AlphaTabApiBase<TSettings> {
this.uiFacade.triggerEvent(this.container, 'beatMouseMove', beat, originalEvent);
}

private onNoteMouseMove(originalEvent: IMouseEventArgs, note: Note): void {
if (this._isDestroyed) {
return;
}

(this.noteMouseMove as EventEmitterOfT<Note>).trigger(note);
this.uiFacade.triggerEvent(this.container, 'noteMouseMove', note, originalEvent);
}

private onBeatMouseUp(originalEvent: IMouseEventArgs, beat: Beat | null): void {
if (this._isDestroyed) {
return;
Expand Down Expand Up @@ -1127,6 +1151,17 @@ export class AlphaTabApiBase<TSettings> {
this._beatMouseDown = false;
}


private onNoteMouseUp(originalEvent: IMouseEventArgs, note: Note | null): void {
if (this._isDestroyed) {
return;
}

(this.noteMouseUp as EventEmitterOfT<Note | null>).trigger(note);
this.uiFacade.triggerEvent(this.container, 'noteMouseUp', note, originalEvent);
this._noteMouseDown = false;
}

private updateSelectionCursor(range: PlaybackRange | null) {
if (!this._tickCache) {
return;
Expand Down Expand Up @@ -1157,6 +1192,14 @@ export class AlphaTabApiBase<TSettings> {
let beat: Beat | null = this.renderer.boundsLookup?.getBeatAtPos(relX, relY) ?? null;
if (beat) {
this.onBeatMouseDown(e, beat);

if (this.settings.core.includeNoteBounds) {
const note = this.renderer.boundsLookup?.getNoteAtPos(beat, relX, relY);
if (note) {
this.onNoteMouseDown(e, note);
}
}

}
});
this.canvasElement.mouseMove.on(e => {
Expand All @@ -1168,6 +1211,13 @@ export class AlphaTabApiBase<TSettings> {
let beat: Beat | null = this.renderer.boundsLookup?.getBeatAtPos(relX, relY) ?? null;
if (beat) {
this.onBeatMouseMove(e, beat);

if (this._noteMouseDown) {
const note = this.renderer.boundsLookup?.getNoteAtPos(beat, relX, relY);
if (note) {
this.onNoteMouseMove(e, note);
}
}
}
});
this.canvasElement.mouseUp.on(e => {
Expand All @@ -1181,6 +1231,16 @@ export class AlphaTabApiBase<TSettings> {
let relY: number = e.getY(this.canvasElement);
let beat: Beat | null = this.renderer.boundsLookup?.getBeatAtPos(relX, relY) ?? null;
this.onBeatMouseUp(e, beat);

if (this._noteMouseDown) {
if (beat) {
const note = this.renderer.boundsLookup?.getNoteAtPos(beat, relX, relY) ?? null;
this.onNoteMouseUp(e, note);
}
else {
this.onNoteMouseUp(e, null);
}
}
});
this.renderer.postRenderFinished.on(() => {
if (
Expand Down
2 changes: 1 addition & 1 deletion src/midi/MidiFileGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1362,7 +1362,7 @@ export class MidiFileGenerator {
this.prepareSingleBeat(note.beat);
this.generateNote(
note,
-note.beat.playbackStart,
0,
note.beat.playbackDuration,
new Int32Array(note.beat.voice.bar.staff.tuning.length)
);
Expand Down
7 changes: 4 additions & 3 deletions src/platform/javascript/AlphaSynthAudioWorkletOutput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Environment } from '@src/Environment';
import { Logger } from '@src/Logger';
import { AlphaSynthWorkerSynthOutput } from '@src/platform/javascript/AlphaSynthWorkerSynthOutput';
import { AlphaSynthWebAudioOutputBase } from '@src/platform/javascript/AlphaSynthWebAudioOutputBase';
import { SynthConstants } from '@src/synth/SynthConstants';

/**
* @target web
Expand Down Expand Up @@ -58,7 +59,7 @@ export class AlphaSynthWebWorklet {
constructor(...args: any[]) {
super(...args);

Logger.info('WebAudio', 'creating processor');
Logger.debug('WebAudio', 'creating processor');

this._bufferCount = Math.floor(
(AlphaSynthWebWorkletProcessor.TotalBufferTimeInMilliseconds *
Expand Down Expand Up @@ -110,15 +111,15 @@ export class AlphaSynthWebWorklet {
buffer = new Float32Array(samples);
this._outputBuffer = buffer;
}
this._circularBuffer.read(buffer, 0, Math.min(buffer.length, this._circularBuffer.count));
const samplesFromBuffer = 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++) {
left[i] = buffer[s++];
right[i] = buffer[s++];
}
this.port.postMessage({
cmd: AlphaSynthWorkerSynthOutput.CmdOutputSamplesPlayed,
samples: left.length
samples: samplesFromBuffer / SynthConstants.AudioChannels
});
this.requestBuffers();

Expand Down
5 changes: 3 additions & 2 deletions src/platform/javascript/AlphaSynthScriptProcessorOutput.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { CircularSampleBuffer } from '@src/synth/ds/CircularSampleBuffer';
import { AlphaSynthWebAudioOutputBase } from '@src/platform/javascript/AlphaSynthWebAudioOutputBase';
import { SynthConstants } from '@src/synth/SynthConstants';

// tslint:disable: deprecation

Expand Down Expand Up @@ -86,13 +87,13 @@ export class AlphaSynthScriptProcessorOutput extends AlphaSynthWebAudioOutputBas
buffer = new Float32Array(samples);
this._outputBuffer = buffer;
}
this._circularBuffer.read(buffer, 0, Math.min(buffer.length, this._circularBuffer.count));
const samplesFromBuffer = 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++) {
left[i] = buffer[s++];
right[i] = buffer[s++];
}
this.onSamplesPlayed(left.length);
this.onSamplesPlayed(samplesFromBuffer / SynthConstants.AudioChannels);
this.requestBuffers();
}
}
4 changes: 3 additions & 1 deletion src/platform/javascript/BrowserUiFacade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,9 @@ export class BrowserUiFacade implements IUiFacade<unknown> {
// remember which bar is contained in which node for faster lookup
// on highlight/unhighlight
for (let i = renderResult.firstMasterBarIndex; i <= renderResult.lastMasterBarIndex; i++) {
this._barToElementLookup.set(i, placeholder);
if(i >= 0) {
this._barToElementLookup.set(i, placeholder);
}
}

if (this._api.settings.core.enableLazyLoading) {
Expand Down
4 changes: 2 additions & 2 deletions src/rendering/RenderFinishedEventArgs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ export class RenderFinishedEventArgs {
/**
* Gets or sets the index of the first masterbar that was rendered in this result.
*/
public firstMasterBarIndex: number = 0;
public firstMasterBarIndex: number = -1;

/**
* Gets or sets the index of the last masterbar that was rendered in this result.
*/
public lastMasterBarIndex: number = 0;
public lastMasterBarIndex: number = -1;

/**
* Gets or sets the render engine specific result object which contains the rendered music sheet.
Expand Down
2 changes: 1 addition & 1 deletion src/rendering/glyphs/NoteNumberGlyph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,6 @@ export class NoteNumberGlyph extends Glyph {
noteBounds.noteHeadBounds.y = cy + this.y - this.height/2;
noteBounds.noteHeadBounds.w = this.width;
noteBounds.noteHeadBounds.h = this.height;
this.renderer.scoreRenderer.boundsLookup!.addNote(noteBounds);
beatBounds.addNote(noteBounds);
}
}
6 changes: 0 additions & 6 deletions src/rendering/layout/PageViewLayout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,6 @@ export class PageViewLayout extends ScoreLayout {
e.height = tuningHeight;
e.totalWidth = this.width;
e.totalHeight = totalHeight < 0 ? y + e.height : totalHeight;
e.firstMasterBarIndex = -1;
e.lastMasterBarIndex = -1;

this.registerPartial(e, (canvas: ICanvas) => {
canvas.color = res.scoreInfoColor;
Expand Down Expand Up @@ -151,8 +149,6 @@ export class PageViewLayout extends ScoreLayout {
e.height = diagramHeight;
e.totalWidth = this.width;
e.totalHeight = totalHeight < 0 ? y + diagramHeight : totalHeight;
e.firstMasterBarIndex = -1;
e.lastMasterBarIndex = -1;

this.registerPartial(e, (canvas: ICanvas) => {
canvas.color = res.scoreInfoColor;
Expand Down Expand Up @@ -218,8 +214,6 @@ export class PageViewLayout extends ScoreLayout {
e.height = infoHeight;
e.totalWidth = this.width;
e.totalHeight = totalHeight < 0 ? y + e.height : totalHeight;
e.firstMasterBarIndex = -1;
e.lastMasterBarIndex = -1;
this.registerPartial(e, (canvas: ICanvas) => {
canvas.color = res.scoreInfoColor;
canvas.textAlign = TextAlign.Center;
Expand Down
39 changes: 24 additions & 15 deletions src/rendering/utils/BoundsLookup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export class BoundsLookup {
return json;
}

private _beatLookup: Map<number, BeatBounds> = new Map();
private _beatLookup: Map<number, BeatBounds[]> = new Map();
private _masterBarLookup: Map<number, MasterBarBounds> = new Map();
private _currentStaveGroup: StaveGroupBounds | null = null;
/**
Expand All @@ -151,15 +151,6 @@ export class BoundsLookup {
this.isFinished = true;
}

/**
* Adds a new note to the lookup.
* @param bounds The note bounds to add.
*/
public addNote(bounds: NoteBounds): void {
let beat = this.findBeat(bounds.note.beat);
beat!.addNote(bounds);
}

/**
* Adds a new stave group to the lookup.
* @param bounds The stave group bounds to add.
Expand Down Expand Up @@ -190,7 +181,10 @@ export class BoundsLookup {
* @param bounds The beat bounds to add.
*/
public addBeat(bounds: BeatBounds): void {
this._beatLookup.set(bounds.beat.id, bounds);
if (!this._beatLookup.has(bounds.beat.id)) {
this._beatLookup.set(bounds.beat.id, []);
}
this._beatLookup.get(bounds.beat.id)?.push(bounds);
}

/**
Expand Down Expand Up @@ -224,6 +218,16 @@ export class BoundsLookup {
* @returns The beat bounds if it was rendered, or null if no boundary information is available.
*/
public findBeat(beat: Beat): BeatBounds | null {
const all = this.findBeats(beat);
return all ? all[0] : null;
}

/**
* Tries to find the bounds of a given beat.
* @param beat The beat to find.
* @returns The beat bounds if it was rendered, or null if no boundary information is available.
*/
public findBeats(beat: Beat): BeatBounds[] | null {
let id: number = beat.id;
if (this._beatLookup.has(id)) {
return this._beatLookup.get(id)!;
Expand Down Expand Up @@ -281,10 +285,15 @@ export class BoundsLookup {
* @returns The note at the given position within the beat.
*/
public getNoteAtPos(beat: Beat, x: number, y: number): Note | null {
let beatBounds: BeatBounds | null = this.findBeat(beat);
if (!beatBounds) {
return null;
const beatBounds = this.findBeats(beat);
if (beatBounds) {
for (const b of beatBounds) {
const note = b.findNoteAtPos(x, y);
if (note) {
return note;
}
}
}
return beatBounds.findNoteAtPos(x, y);
return null;
}
}
Loading