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

Multiple Soundfont support #380

Merged
merged 4 commits into from
Jul 26, 2020
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
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,14 @@ public void Stop()
DispatchOnWorkerThread(() => { Player.Stop(); });
}

public void LoadSoundFont(Uint8Array data)
public void ResetSoundFonts()
{
DispatchOnWorkerThread(() => { Player.LoadSoundFont(data); });
DispatchOnWorkerThread(() => { Player.ResetSoundFonts(); });
}

public void LoadSoundFont(Uint8Array data, bool append)
{
DispatchOnWorkerThread(() => { Player.LoadSoundFont(data, append); });
}

public void LoadMidiFile(MidiFile midi)
Expand Down
8 changes: 4 additions & 4 deletions src.csharp/AlphaTab/Platform/CSharp/ManagedUiFacade.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public IAlphaSynth CreateWorkerPlayer()
using (var ms = new MemoryStream())
{
sf.CopyTo(ms);
player.LoadSoundFont(new Uint8Array(ms.ToArray()));
player.LoadSoundFont(new Uint8Array(ms.ToArray()), false);
}
});
return player;
Expand Down Expand Up @@ -124,19 +124,19 @@ public bool Load(object? data, Action<Score> success, Action<Error> error)
}
}

public bool LoadSoundFont(object? data)
public bool LoadSoundFont(object? data, bool append)
{
switch (data)
{
case byte[] bytes:
Api.Player.LoadSoundFont(new Uint8Array(bytes));
Api.Player.LoadSoundFont(new Uint8Array(bytes), append);
return true;
case Stream stream:
{
using (var ms = new MemoryStream())
{
stream.CopyTo(ms);
Api.Player.LoadSoundFont(new Uint8Array(ms.ToArray()));
Api.Player.LoadSoundFont(new Uint8Array(ms.ToArray()), append);
}

return true;
Expand Down
2 changes: 1 addition & 1 deletion src.csharp/Samples/AlphaTab.Samples.Player/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ private static void Main(string[] args)
currentTime, e.CurrentTick, endTime, e.EndTick);
});
player.ReadyForPlayback.On(() => { Console.WriteLine("Ready for playback"); });
player.LoadSoundFont(File.ReadAllBytes(args[1]));
player.LoadSoundFont(File.ReadAllBytes(args[1]), false);
player.LoadMidiFile(midiFile);

Console.WriteLine("Start playing");
Expand Down
24 changes: 20 additions & 4 deletions src/AlphaTabApiBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,12 @@ export class AlphaTabApiBase<TSettings> {
let score: Score = tracks[0].score;
for (let track of tracks) {
if (track.score !== score) {
this.onError(new AlphaTabError(AlphaTabErrorType.General, 'All rendered tracks must belong to the same score.'));
this.onError(
new AlphaTabError(
AlphaTabErrorType.General,
'All rendered tracks must belong to the same score.'
)
);
return;
}
}
Expand Down Expand Up @@ -334,13 +339,24 @@ export class AlphaTabApiBase<TSettings> {
/**
* Attempts a load of the score represented by the given data object.
* @param data The data object to decode
* @param append Whether to fully replace or append the data from the given soundfont.
* @returns true if the data object is supported and a load was initiated, otherwise false
*/
public loadSoundFont(data: unknown): boolean {
public loadSoundFont(data: unknown, append: boolean = false): boolean {
if (!this.player) {
return false;
}
return this.uiFacade.loadSoundFont(data);
return this.uiFacade.loadSoundFont(data, append);
}

/**
* Resets all loaded soundfonts as if they were not loaded.
*/
public resetSoundFonts(): void {
if (!this.player) {
return;
}
this.player.resetSoundFonts();
}

/**
Expand Down Expand Up @@ -915,7 +931,7 @@ export class AlphaTabApiBase<TSettings> {
);
// move to selection start
this._currentBeat = null; // reset current beat so it is updating the cursor
if(this._playerState === PlayerState.Paused) {
if (this._playerState === PlayerState.Paused) {
this.cursorUpdateBeat(this._selectionStart.beat, null, 0, false, [this._selectionStart.beat]);
}
this.tickPosition = realMasterBarStart + this._selectionStart.beat.playbackStart;
Expand Down
3 changes: 2 additions & 1 deletion src/platform/IUiFacade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,10 @@ export interface IUiFacade<TSettings> {
/**
* Attempts a load of the score represented by the given data object.
* @param data The data object to decode
* @param append Whether to fully replace or append the data from the given soundfont.
* @returns true if the data object is supported and a load was initiated, otherwise false
*/
loadSoundFont(data: unknown): boolean;
loadSoundFont(data: unknown, append: boolean): boolean;

/**
* This events is fired when the {@link canRender} property changes.
Expand Down
36 changes: 4 additions & 32 deletions src/platform/javascript/AlphaSynthWebWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,6 @@ import { Environment } from '@src/Environment';
* @target web
*/
export class AlphaSynthWebWorker {
public static readonly CmdPrefix: string = 'alphaSynth.';
public static readonly CmdInitialize: string = AlphaSynthWebWorker.CmdPrefix + 'initialize';
public static readonly CmdSetLogLevel: string = AlphaSynthWebWorker.CmdPrefix + 'setLogLevel';
public static readonly CmdSetMasterVolume: string = AlphaSynthWebWorker.CmdPrefix + 'setMasterVolume';
public static readonly CmdSetMetronomeVolume: string = AlphaSynthWebWorker.CmdPrefix + 'setMetronomeVolume';
public static readonly CmdSetPlaybackSpeed: string = AlphaSynthWebWorker.CmdPrefix + 'setPlaybackSpeed';
public static readonly CmdSetTickPosition: string = AlphaSynthWebWorker.CmdPrefix + 'setTickPosition';
public static readonly CmdSetTimePosition: string = AlphaSynthWebWorker.CmdPrefix + 'setTimePosition';
public static readonly CmdSetPlaybackRange: string = AlphaSynthWebWorker.CmdPrefix + 'setPlaybackRange';
public static readonly CmdSetIsLooping: string = AlphaSynthWebWorker.CmdPrefix + 'setIsLooping';
public static readonly CmdPlay: string = AlphaSynthWebWorker.CmdPrefix + 'play';
public static readonly CmdPause: string = AlphaSynthWebWorker.CmdPrefix + 'pause';
public static readonly CmdPlayPause: string = AlphaSynthWebWorker.CmdPrefix + 'playPause';
public static readonly CmdStop: string = AlphaSynthWebWorker.CmdPrefix + 'stop';
public static readonly CmdLoadSoundFontBytes: string = AlphaSynthWebWorker.CmdPrefix + 'loadSoundFontBytes';
public static readonly CmdLoadMidi: string = AlphaSynthWebWorker.CmdPrefix + 'loadMidi';
public static readonly CmdSetChannelMute: string = AlphaSynthWebWorker.CmdPrefix + 'setChannelMute';
public static readonly CmdSetChannelSolo: string = AlphaSynthWebWorker.CmdPrefix + 'setChannelSolo';
public static readonly CmdSetChannelVolume: string = AlphaSynthWebWorker.CmdPrefix + 'setChannelVolume';
public static readonly CmdResetChannelStates: string = AlphaSynthWebWorker.CmdPrefix + 'resetChannelStates';
public static readonly CmdReady: string = AlphaSynthWebWorker.CmdPrefix + 'ready';
public static readonly CmdReadyForPlayback: string = AlphaSynthWebWorker.CmdPrefix + 'readyForPlayback';
public static readonly CmdPositionChanged: string = AlphaSynthWebWorker.CmdPrefix + 'positionChanged';
public static readonly CmdPlayerStateChanged: string = AlphaSynthWebWorker.CmdPrefix + 'playerStateChanged';
public static readonly CmdFinished: string = AlphaSynthWebWorker.CmdPrefix + 'finished';
public static readonly CmdSoundFontLoaded: string = AlphaSynthWebWorker.CmdPrefix + 'soundFontLoaded';
public static readonly CmdSoundFontLoadFailed: string = AlphaSynthWebWorker.CmdPrefix + 'soundFontLoadFailed';
public static readonly CmdMidiLoaded: string = AlphaSynthWebWorker.CmdPrefix + 'midiLoaded';
public static readonly CmdMidiLoadFailed: string = AlphaSynthWebWorker.CmdPrefix + 'midiLoadFailed';
public static readonly CmdLog: string = AlphaSynthWebWorker.CmdPrefix + 'log';

private _player: AlphaSynth;
private _main: IWorkerScope;

Expand Down Expand Up @@ -122,7 +91,10 @@ export class AlphaSynthWebWorker {
this._player.stop();
break;
case 'alphaSynth.loadSoundFontBytes':
this._player.loadSoundFont(data.data);
this._player.loadSoundFont(data.data, data.append);
break;
case 'alphaSynth.resetSoundFonts':
this._player.resetSoundFonts();
break;
case 'alphaSynth.loadMidi':
this._player.loadMidiFile(JsonConverter.jsObjectToMidiFile(data.midi));
Expand Down
22 changes: 13 additions & 9 deletions src/platform/javascript/AlphaSynthWebWorkerApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import { PlayerStateChangedEventArgs } from '@src/synth/PlayerStateChangedEventA
import { PositionChangedEventArgs } from '@src/synth/PositionChangedEventArgs';
import { SynthHelper } from '@src/synth/SynthHelper';
import { EventEmitter, IEventEmitter, IEventEmitterOfT, EventEmitterOfT } from '@src/EventEmitter';
import { FileLoadError } from '@src/FileLoadError';
import { JsonConverter } from '@src/model/JsonConverter';
import { ProgressEventArgs } from '@src/ProgressEventArgs';
import { Logger } from '@src/Logger';
import { LogLevel } from '@src/LogLevel';
import { SynthConstants } from '@src/synth/SynthConstants';
import { ProgressEventArgs } from '@src/alphatab';
import { FileLoadError } from '@src/FileLoadError';

/**
* a WebWorker based alphaSynth which uses the given player as output.
Expand Down Expand Up @@ -236,24 +236,22 @@ export class AlphaSynthWebWorkerApi implements IAlphaSynth {
});
}

public loadSoundFont(data: Uint8Array): void {
public loadSoundFont(data: Uint8Array, append: boolean): void {
this._synth.postMessage({
cmd: 'alphaSynth.loadSoundFontBytes',
data: data
data: data,
append: append
});
}

public loadSoundFontFromUrl(url: string, progress: (e: ProgressEventArgs) => void): void {
public loadSoundFontFromUrl(url: string, append: boolean, progress: (e: ProgressEventArgs) => void): void {
Logger.debug('AlphaSynth', `Start loading Soundfont from url ${url}`);
let request: XMLHttpRequest = new XMLHttpRequest();
request.open('GET', url, true, null, null);
request.responseType = 'arraybuffer';
request.onload = _ => {
let buffer: Uint8Array = new Uint8Array(request.response);
this._synth.postMessage({
cmd: 'alphaSynth.loadSoundFontBytes',
data: buffer
});
this.loadSoundFont(buffer, append);
};
request.onerror = e => {
Logger.error('AlphaSynth', 'Loading failed: ' + (e as any).message);
Expand All @@ -268,6 +266,12 @@ export class AlphaSynthWebWorkerApi implements IAlphaSynth {
request.send();
}

public resetSoundFonts(): void {
this._synth.postMessage({
cmd: 'alphaSynth.resetSoundFonts'
});
}

public loadMidiFile(midi: MidiFile): void {
this._synth.postMessage({
cmd: 'alphaSynth.loadMidi',
Expand Down
3 changes: 2 additions & 1 deletion src/platform/javascript/AlphaTabApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,13 @@ export class AlphaTabApi extends AlphaTabApiBase<unknown> {
}

public soundFontLoad: IEventEmitterOfT<ProgressEventArgs> = new EventEmitterOfT<ProgressEventArgs>();
public loadSoundFontFromUrl(url: string): void {
public loadSoundFontFromUrl(url: string, append: boolean): void {
if (!this.player) {
return;
}
(this.player as AlphaSynthWebWorkerApi).loadSoundFontFromUrl(
url,
append,
e => {
(this.soundFontLoad as EventEmitterOfT<ProgressEventArgs>).trigger(e);
this.uiFacade.triggerEvent(this.container, 'soundFontLoad', e);
Expand Down
10 changes: 5 additions & 5 deletions src/platform/javascript/BrowserUiFacade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,21 +235,21 @@ export class BrowserUiFacade implements IUiFacade<unknown> {
return false;
}

public loadSoundFont(data: unknown): boolean {
public loadSoundFont(data: unknown, append: boolean): boolean {
if (!this._api.player) {
return false;
}

if (data instanceof ArrayBuffer) {
this._api.player.loadSoundFont(new Uint8Array(data));
this._api.player.loadSoundFont(new Uint8Array(data), append);
return true;
}
if (data instanceof Uint8Array) {
this._api.player.loadSoundFont(data);
this._api.player.loadSoundFont(data, append);
return true;
}
if (typeof data === 'string') {
(this._api as AlphaTabApi).loadSoundFontFromUrl(data);
(this._api as AlphaTabApi).loadSoundFontFromUrl(data, append);
return true;
}
return false;
Expand Down Expand Up @@ -475,7 +475,7 @@ export class BrowserUiFacade implements IUiFacade<unknown> {
} else {
player.ready.on(() => {
if (this._api.settings.player.soundFont) {
(this._api as AlphaTabApi).loadSoundFontFromUrl(this._api.settings.player.soundFont);
(this._api as AlphaTabApi).loadSoundFontFromUrl(this._api.settings.player.soundFont, false);
}
});
}
Expand Down
8 changes: 6 additions & 2 deletions src/platform/javascript/JQueryAlphaTab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,12 @@ export class JQueryAlphaTab {
context.changeTrackVolume(tracks, volume);
}

public loadSoundFont(element: jQuery, context: AlphaTabApi, value: unknown): void {
context.loadSoundFont(value);
public loadSoundFont(element: jQuery, context: AlphaTabApi, value: unknown, append: boolean): void {
context.loadSoundFont(value, append);
}

public resetSoundFonts(element: jQuery, context: AlphaTabApi): void {
context.resetSoundFonts();
}

public pause(element: jQuery, context: AlphaTabApi): void {
Expand Down
11 changes: 9 additions & 2 deletions src/synth/AlphaSynth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,15 +223,22 @@ export class AlphaSynth implements IAlphaSynth {
);
}

public loadSoundFont(data: Uint8Array): void {
public resetSoundFonts(): void {
this.stop();
this._synthesizer.resetPresets();
this._isSoundFontLoaded = false;
(this.soundFontLoaded as EventEmitter).trigger();
}

public loadSoundFont(data: Uint8Array, append:boolean): void {
this.pause();

let input: ByteBuffer = ByteBuffer.fromBuffer(data);
try {
Logger.debug('AlphaSynth', 'Loading soundfont from bytes');
let soundFont: Hydra = new Hydra();
soundFont.load(input);
this._synthesizer.loadPresets(soundFont);
this._synthesizer.loadPresets(soundFont, append);
this._isSoundFontLoaded = true;
(this.soundFontLoaded as EventEmitter).trigger();

Expand Down
8 changes: 7 additions & 1 deletion src/synth/IAlphaSynth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,14 @@ export interface IAlphaSynth {
/**
* Loads a soundfont from the given data
* @param data a byte array to load the data from
* @param append Whether to fully replace or append the data from the given soundfont.
*/
loadSoundFont(data: Uint8Array): void;
loadSoundFont(data: Uint8Array, append: boolean): void;

/**
* Resets all loaded soundfonts as if they were not loaded.
*/
resetSoundFonts(): void;

/**
* Loads the given midi file structure.
Expand Down
1 change: 1 addition & 0 deletions src/synth/synthesis/Preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ export class Preset {
public presetNumber: number = 0;
public bank: number = 0;
public regions: Region[] | null = null;
public fontSamples: Float32Array | null = null;
}
Loading