@dawcore/components 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -755,7 +755,12 @@ DawStopButtonElement = __decorateClass([
755
755
  // src/elements/daw-editor.ts
756
756
  import { LitElement as LitElement8, html as html7, css as css7 } from "lit";
757
757
  import { customElement as customElement10, property as property6, state as state3 } from "lit/decorators.js";
758
- import { createClipFromSeconds as createClipFromSeconds2, createTrack as createTrack2, clipPixelWidth } from "@waveform-playlist/core";
758
+ import {
759
+ createClip as createClip2,
760
+ createClipFromSeconds as createClipFromSeconds2,
761
+ createTrack as createTrack2,
762
+ clipPixelWidth
763
+ } from "@waveform-playlist/core";
759
764
 
760
765
  // src/workers/peaksWorker.ts
761
766
  import WaveformData from "waveform-data";
@@ -2912,6 +2917,7 @@ var DawEditorElement = class extends LitElement8 {
2912
2917
  this._onTrackRemoved(trackId);
2913
2918
  }
2914
2919
  };
2920
+ this._contextConfigurePromise = null;
2915
2921
  // --- File Drop ---
2916
2922
  this._onDragOver = (e) => {
2917
2923
  if (!this.fileDrop) return;
@@ -3063,6 +3069,7 @@ var DawEditorElement = class extends LitElement8 {
3063
3069
  this._clipOffsets.clear();
3064
3070
  this._peakPipeline.terminate();
3065
3071
  this._minSamplesPerPixel = 0;
3072
+ this._contextConfigurePromise = null;
3066
3073
  try {
3067
3074
  this._disposeEngine();
3068
3075
  } catch (err) {
@@ -3171,7 +3178,17 @@ var DawEditorElement = class extends LitElement8 {
3171
3178
  let waveformData = null;
3172
3179
  if (waveformDataPromise) {
3173
3180
  try {
3174
- waveformData = await waveformDataPromise;
3181
+ const wd = await waveformDataPromise;
3182
+ await this._ensureContextConfigured();
3183
+ const { getGlobalAudioContext } = await import("@waveform-playlist/playout");
3184
+ const contextRate = getGlobalAudioContext().sampleRate;
3185
+ if (wd.sample_rate === contextRate) {
3186
+ waveformData = wd;
3187
+ } else {
3188
+ console.warn(
3189
+ "[dawcore] Pre-computed peaks at " + wd.sample_rate + " Hz do not match AudioContext at " + contextRate + " Hz \u2014 ignoring " + clipDesc.peaksSrc + ", generating from audio"
3190
+ );
3191
+ }
3175
3192
  } catch (err) {
3176
3193
  console.warn(
3177
3194
  "[dawcore] Failed to load peaks from " + clipDesc.peaksSrc + ": " + String(err) + " \u2014 falling back to AudioBuffer generation"
@@ -3179,15 +3196,16 @@ var DawEditorElement = class extends LitElement8 {
3179
3196
  }
3180
3197
  }
3181
3198
  if (waveformData) {
3182
- const clip2 = createClipFromSeconds2({
3199
+ const wdRate = waveformData.sample_rate;
3200
+ const clip2 = createClip2({
3183
3201
  waveformData,
3184
- startTime: clipDesc.start,
3185
- duration: clipDesc.duration || waveformData.duration,
3186
- offset: clipDesc.offset,
3202
+ startSample: Math.round(clipDesc.start * wdRate),
3203
+ durationSamples: Math.round((clipDesc.duration || waveformData.duration) * wdRate),
3204
+ offsetSamples: Math.round(clipDesc.offset * wdRate),
3187
3205
  gain: clipDesc.gain,
3188
3206
  name: clipDesc.name,
3189
- sampleRate: waveformData.sample_rate,
3190
- sourceDuration: waveformData.duration
3207
+ sampleRate: wdRate,
3208
+ sourceDurationSamples: Math.ceil(waveformData.duration * wdRate)
3191
3209
  });
3192
3210
  const effectiveScale = Math.max(this.samplesPerPixel, waveformData.scale);
3193
3211
  const peakData2 = extractPeaks(
@@ -3295,6 +3313,30 @@ var DawEditorElement = class extends LitElement8 {
3295
3313
  );
3296
3314
  }
3297
3315
  }
3316
+ /**
3317
+ * Ensure the global AudioContext is configured with the editor's sample-rate hint
3318
+ * before the first audio operation. Idempotent — concurrent callers await the
3319
+ * same promise so no one proceeds to getGlobalAudioContext() before configuration.
3320
+ */
3321
+ _ensureContextConfigured() {
3322
+ if (!this._contextConfigurePromise) {
3323
+ this._contextConfigurePromise = (async () => {
3324
+ const { configureGlobalContext } = await import("@waveform-playlist/playout");
3325
+ const actualRate = configureGlobalContext({
3326
+ sampleRate: this.sampleRate
3327
+ });
3328
+ if (actualRate !== this.sampleRate) {
3329
+ console.warn(
3330
+ "[dawcore] Requested sampleRate " + this.sampleRate + " but AudioContext is running at " + actualRate
3331
+ );
3332
+ }
3333
+ })().catch((err) => {
3334
+ this._contextConfigurePromise = null;
3335
+ throw err;
3336
+ });
3337
+ }
3338
+ return this._contextConfigurePromise;
3339
+ }
3298
3340
  async _fetchAndDecode(src) {
3299
3341
  if (this._audioCache.has(src)) {
3300
3342
  return this._audioCache.get(src);
@@ -3307,6 +3349,7 @@ var DawEditorElement = class extends LitElement8 {
3307
3349
  );
3308
3350
  }
3309
3351
  const arrayBuffer = await response.arrayBuffer();
3352
+ await this._ensureContextConfigured();
3310
3353
  const { getGlobalAudioContext } = await import("@waveform-playlist/playout");
3311
3354
  return getGlobalAudioContext().decodeAudioData(arrayBuffer);
3312
3355
  })();