Files
clawbot/skills/remotion-prompt-video/node_modules/@remotion/webcodecs/dist/convert-audiodata.js

86 lines
3.7 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertAudioData = void 0;
const data_types_1 = require("./audio-data/data-types");
const is_planar_format_1 = require("./audio-data/is-planar-format");
const validateRange = (format, value) => {
if (format === 'f32' || format === 'f32-planar') {
if (value < -1 || value > 1) {
throw new Error('All values in a Float32 array must be between -1 and 1');
}
}
};
/**
* Converts an `AudioData` object to a new `AudioData` object with a different sample rate or format.
* @see [Documentation](https://remotion.dev/docs/webcodecs/convert-audiodata)
*/
const convertAudioData = ({ audioData, newSampleRate = audioData.sampleRate, format = audioData.format, }) => {
const { numberOfChannels, sampleRate: currentSampleRate, numberOfFrames: currentNumberOfFrames, } = audioData;
const ratio = currentSampleRate / newSampleRate;
const newNumberOfFrames = Math.floor(currentNumberOfFrames / ratio);
if (newNumberOfFrames === 0) {
throw new Error('Cannot resample - the given sample rate would result in less than 1 sample');
}
if (newSampleRate < 3000 || newSampleRate > 768000) {
throw new Error('newSampleRate must be between 3000 and 768000');
}
if (!format) {
throw new Error('AudioData format is not set');
}
if (format === audioData.format &&
newNumberOfFrames === currentNumberOfFrames) {
return audioData.clone();
}
const DataType = (0, data_types_1.getDataTypeForAudioFormat)(format);
const isPlanar = (0, is_planar_format_1.isPlanarFormat)(format);
const planes = isPlanar ? numberOfChannels : 1;
const srcChannels = new Array(planes)
.fill(true)
.map(() => new DataType((isPlanar ? 1 : numberOfChannels) * currentNumberOfFrames));
for (let i = 0; i < planes; i++) {
audioData.clone().copyTo(srcChannels[i], {
planeIndex: i,
format,
});
}
const data = new DataType(newNumberOfFrames * numberOfChannels);
const chunkSize = currentNumberOfFrames / newNumberOfFrames;
for (let newFrameIndex = 0; newFrameIndex < newNumberOfFrames; newFrameIndex++) {
const start = Math.floor(newFrameIndex * chunkSize);
const end = Math.max(Math.floor(start + chunkSize), start + 1);
if (isPlanar) {
for (let channelIndex = 0; channelIndex < numberOfChannels; channelIndex++) {
const chunk = srcChannels[channelIndex].slice(start, end);
const average = chunk.reduce((a, b) => {
return a + b;
}, 0) / chunk.length;
validateRange(format, average);
data[newFrameIndex + channelIndex * newNumberOfFrames] = average;
}
}
else {
const sampleCountAvg = end - start;
for (let channelIndex = 0; channelIndex < numberOfChannels; channelIndex++) {
const items = [];
for (let k = 0; k < sampleCountAvg; k++) {
const num = srcChannels[0][(start + k) * numberOfChannels + channelIndex];
items.push(num);
}
const average = items.reduce((a, b) => a + b, 0) / items.length;
validateRange(format, average);
data[newFrameIndex * numberOfChannels + channelIndex] = average;
}
}
}
const newAudioData = new AudioData({
data,
format,
numberOfChannels,
numberOfFrames: newNumberOfFrames,
sampleRate: newSampleRate,
timestamp: audioData.timestamp,
});
return newAudioData;
};
exports.convertAudioData = convertAudioData;