Skip to content

Commit

Permalink
Skip initial audio rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
Eliastik committed Mar 25, 2024
1 parent 78f67ae commit b54571e
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 14 deletions.
2 changes: 1 addition & 1 deletion dist/cjs/SimpleSoundStudioLibrary.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/cjs/SimpleSoundStudioLibrary.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/esm/SimpleSoundStudioLibrary.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/esm/SimpleSoundStudioLibrary.js.map

Large diffs are not rendered by default.

16 changes: 14 additions & 2 deletions dist/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ interface ConfigService {
* Return the base path for audio files (reverb environments for example)
*/
getSoundBasePath(): string;
/**
* Check if initial audio rendering (when openin a file or buffer) is disabled
*/
isInitialRenderingDisabled(): boolean;
}

declare class BufferFetcherService {
Expand Down Expand Up @@ -384,9 +388,10 @@ declare class AudioEditor extends AbstractAudioElement {
/**
* Render the audio to a buffer
* @returns A promise resolved when the audio processing is finished.
* The promise return false if the audio processing was cancelled or if an error occurred.
* The resulting audio buffer can then be obtained by using the "getOutputBuffer" method.
*/
renderAudio(): Promise<void>;
renderAudio(): Promise<boolean>;
/**
* Execute audio renderers then returns audio buffer rendered
* @param outputContext The output context
Expand All @@ -403,7 +408,7 @@ declare class AudioEditor extends AbstractAudioElement {
* @param outputContext Output audio context
* @param durationAudio Duration of the audio buffer
* @param offlineContext An offline context to do the rendering (can be omited, in this case the rendering is done in real time - "compatibility mode")
* @returns A promise resolved when the audio processing is done
* @returns A promise resolved when the audio processing is done. The promise returns false if the audio processing was cancelled, or if an error occurred.
*/
private setupOutput;
/**
Expand All @@ -412,6 +417,10 @@ declare class AudioEditor extends AbstractAudioElement {
* @returns false if the rendred audio buffer is invalid, true otherwise
*/
private loadRenderedAudio;
/**
* Load the initial audio buffer to the buffer player
*/
private loadInitialBuffer;
/**
* Cancel the audio rendering
*/
Expand Down Expand Up @@ -803,6 +812,7 @@ declare const Constants: {
ENABLE_SOUNDTOUCH_AUDIO_WORKLET: string;
BUFFER_SIZE: string;
SAMPLE_RATE: string;
DISABLE_INITIAL_RENDERING: string;
};
ENABLE_SOUNDTOUCH_AUDIO_WORKLET: boolean;
ENABLE_AUDIO_WORKLET: boolean;
Expand All @@ -822,6 +832,7 @@ declare const Constants: {
VALID_SAMPLE_RATES: number[];
TREATMENT_TIME_COUNTING_THROTTLE_INTERVAL: number;
TREATMENT_TIME_COUNTING_SMOOTHING_FACTOR: number;
DISABLE_INITIAL_RENDERING: boolean;
};

/**
Expand All @@ -842,6 +853,7 @@ declare class GenericConfigService implements ConfigService {
disableCompatibilityMode(): void;
getWorkletBasePath(): string;
getSoundBasePath(): string;
isInitialRenderingDisabled(): boolean;
}

declare const utilFunctions: {
Expand Down
35 changes: 29 additions & 6 deletions lib/AudioEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,9 +489,10 @@ export default class AudioEditor extends AbstractAudioElement {
/**
* Render the audio to a buffer
* @returns A promise resolved when the audio processing is finished.
* The promise return false if the audio processing was cancelled or if an error occurred.
* The resulting audio buffer can then be obtained by using the "getOutputBuffer" method.
*/
async renderAudio(): Promise<void> {
async renderAudio(): Promise<boolean> {
await this.prepareContext();

if (!this.currentContext) {
Expand All @@ -502,6 +503,12 @@ export default class AudioEditor extends AbstractAudioElement {
throw new Error("Entrypoint filter is not available");
}

if (!this.initialRenderingDone && this.configService && this.configService.isInitialRenderingDisabled()) {
this.loadInitialBuffer();
this.initialRenderingDone = true;
return true;
}

const speedAudio = this.entrypointFilter.getSpeed();
const durationAudio = this.calculateAudioDuration(speedAudio);
const offlineContext = new OfflineAudioContext(2, this.currentContext.sampleRate * durationAudio, this.currentContext.sampleRate);
Expand Down Expand Up @@ -551,9 +558,9 @@ export default class AudioEditor extends AbstractAudioElement {
* @param outputContext Output audio context
* @param durationAudio Duration of the audio buffer
* @param offlineContext An offline context to do the rendering (can be omited, in this case the rendering is done in real time - "compatibility mode")
* @returns A promise resolved when the audio processing is done
* @returns A promise resolved when the audio processing is done. The promise returns false if the audio processing was cancelled, or if an error occurred.
*/
private async setupOutput(outputContext: BaseAudioContext, durationAudio?: number, offlineContext?: OfflineAudioContext): Promise<void> {
private async setupOutput(outputContext: BaseAudioContext, durationAudio?: number, offlineContext?: OfflineAudioContext): Promise<boolean> {
if (this.renderedBuffer && this.configService && this.eventEmitter && this.bufferPlayer) {
// Initialize worklets then connect the filter nodes
await this.initializeWorklets(outputContext);
Expand All @@ -575,13 +582,21 @@ export default class AudioEditor extends AbstractAudioElement {
return await this.setupOutput(this.currentContext!, durationAudio);
}

if(this.audioRenderingLastCanceled) {
return false;
}

this.eventEmitter.emit(EventType.OFFLINE_AUDIO_RENDERING_FINISHED);
} else { // Compatibility mode
this.bufferPlayer.setCompatibilityMode(this.currentNodes!.output, durationAudio);
}

this.eventEmitter.emit(EventType.AUDIO_RENDERING_FINISHED);

return true;
}

return false;
}

/**
Expand Down Expand Up @@ -609,9 +624,7 @@ export default class AudioEditor extends AbstractAudioElement {
this.renderedBuffer = renderedBuffer;
this.bufferPlayer.loadBuffer(this.renderedBuffer);
} else if(!this.initialRenderingDone) {
this.renderedBuffer = this.principalBuffer;
this.bufferPlayer.loadBuffer(this.principalBuffer!);

this.loadInitialBuffer();
this.eventEmitter.emit(EventType.CANCELED_AND_LOADED_INITIAL_AUDIO);
}

Expand All @@ -621,6 +634,16 @@ export default class AudioEditor extends AbstractAudioElement {
return true;
}

/**
* Load the initial audio buffer to the buffer player
*/
private loadInitialBuffer() {
if (this.bufferPlayer) {
this.renderedBuffer = this.principalBuffer;
this.bufferPlayer.loadBuffer(this.principalBuffer!);
}
}

/**
* Cancel the audio rendering
*/
Expand Down
7 changes: 5 additions & 2 deletions lib/model/Constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ const Constants = {
ENABLE_AUDIO_WORKLET: "enable-audio-worklet",
ENABLE_SOUNDTOUCH_AUDIO_WORKLET: "enable-soundtouch-audio-worklet",
BUFFER_SIZE: "buffer-size",
SAMPLE_RATE: "sample-rate"
SAMPLE_RATE: "sample-rate",
DISABLE_INITIAL_RENDERING: "disable-initial-rendering"
},
// Enable or disable the use of Audio Worklet version of Soundtouch
// If disabled, the ScriptProcessorNode version is used
Expand All @@ -63,7 +64,9 @@ const Constants = {
// Interval used by the treatment percent counter. The event will be dispatched each ms defined here
TREATMENT_TIME_COUNTING_THROTTLE_INTERVAL: 100,
// Smoothing factor for the time couting estimation (between 0 and 1)
TREATMENT_TIME_COUNTING_SMOOTHING_FACTOR: 0.9
TREATMENT_TIME_COUNTING_SMOOTHING_FACTOR: 0.9,
// Disable initial rendering (when opening audio file or buffer)
DISABLE_INITIAL_RENDERING: true
};

export default Constants;
5 changes: 5 additions & 0 deletions lib/services/ConfigService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,9 @@ export interface ConfigService {
* Return the base path for audio files (reverb environments for example)
*/
getSoundBasePath(): string;

/**
* Check if initial audio rendering (when openin a file or buffer) is disabled
*/
isInitialRenderingDisabled(): boolean;
};
10 changes: 10 additions & 0 deletions lib/utils/GenericConfigService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,14 @@ export default class GenericConfigService implements ConfigService {
getSoundBasePath(): string {
return "";
}

isInitialRenderingDisabled(): boolean {
const setting = this.getConfig(Constants.PREFERENCES_KEYS.DISABLE_INITIAL_RENDERING);

if(setting != null) {
return setting == "true";
}

return Constants.DISABLE_INITIAL_RENDERING;
}
};

0 comments on commit b54571e

Please sign in to comment.