{"version":3,"file":"audioProcessing.21cb49e1.mjs","sources":["../../src/components/ReactFileUtilities/utils.ts","../../src/components/MediaRecorder/transcode/audioProcessing.ts"],"sourcesContent":["import type { FileLike, RecordedMediaType } from './types';\nimport type { ChangeEvent } from 'react';\nimport { useCallback } from 'react';\n\nexport const useHandleFileChangeWrapper = (\n  resetOnChange = false,\n  handler?: (files: Array<File>) => void,\n) =>\n  useCallback(\n    ({ currentTarget }: ChangeEvent<HTMLInputElement>) => {\n      const { files } = currentTarget;\n\n      if (!files) return;\n\n      try {\n        handler?.(Array.from(files));\n      } catch (error) {\n        console.error(error);\n      }\n\n      if (resetOnChange) currentTarget.value = '';\n    },\n    [handler, resetOnChange],\n  );\n\nexport function dataTransferItemsHaveFiles(items?: DataTransferItem[]): boolean {\n  if (!items || !items.length) {\n    return false;\n  }\n  for (const item of items) {\n    if (item.kind === 'file' || item.type === 'text/html') {\n      return true;\n    }\n  }\n  return false;\n}\n\nexport async function dataTransferItemsToFiles(\n  items?: DataTransferItem[],\n): Promise<FileLike[]> {\n  if (!items || !items.length) {\n    return [];\n  }\n\n  // If there are files inside the DataTransferItem prefer those\n  const fileLikes = getFileLikes(items);\n  if (fileLikes.length) {\n    return fileLikes;\n  }\n\n  // Otherwise extract images from html\n  const blobPromises = [];\n  for (const item of items) {\n    if (item.type === 'text/html') {\n      blobPromises.push(\n        new Promise<void>((accept) => {\n          item.getAsString(async (s) => {\n            const imagePromises = extractImageSources(s).map((src) =>\n              getImageSource(fileLikes, src),\n            );\n\n            await Promise.all(imagePromises);\n            accept();\n          });\n        }),\n      );\n    }\n  }\n  await Promise.all(blobPromises);\n  return fileLikes;\n}\n\nfunction getFileLikes(items: DataTransferItem[]) {\n  const fileLikes = [];\n  for (const item of items) {\n    if (item.kind === 'file') {\n      const file = item.getAsFile();\n      if (file) {\n        fileLikes.push(file);\n      }\n    }\n  }\n  return fileLikes;\n}\n\nasync function getImageSource(fileLikes: FileLike[], src: string) {\n  let res;\n  try {\n    res = await fetch(src);\n  } catch (e) {\n    return;\n  }\n  const contentType = res.headers.get('Content-type') || 'application/octet-stream';\n  const buf = await res.arrayBuffer();\n  const blob = new Blob([buf], { type: contentType });\n  fileLikes.push(blob);\n}\n\nconst extractImageSources = (s: string) => {\n  const imageTags = new DOMParser()\n    .parseFromString(s, 'text/html')\n    .getElementsByTagName('img');\n  return Array.from(imageTags, (tag) => tag.src).filter((tag) => tag);\n};\n\nexport const isBlobButNotFile = (obj: unknown): obj is Blob =>\n  obj instanceof Blob && !(obj instanceof File);\n\nexport const createFileFromBlobs = ({\n  blobsArray,\n  fileName,\n  mimeType,\n}: {\n  blobsArray: Blob[];\n  fileName: string;\n  mimeType: string;\n}) => {\n  const concatenatedBlob = new Blob(blobsArray, { type: mimeType });\n  return new File([concatenatedBlob], fileName, { type: concatenatedBlob.type });\n};\n\nexport const getExtensionFromMimeType = (mimeType: string) => {\n  const match = mimeType.match(/\\/([^/;]+)/);\n  return match && match[1];\n};\n\nexport const getRecordedMediaTypeFromMimeType = (\n  mimeType: string,\n): RecordedMediaType | null => {\n  const match = mimeType.match(/^(audio|video)\\/.*$/);\n  return match && (match[1] as RecordedMediaType);\n};\n\nexport const readFileAsArrayBuffer = (file: File): Promise<ArrayBuffer> =>\n  new Promise((resolve, reject) => {\n    const fileReader = new FileReader();\n    fileReader.onload = () => {\n      resolve(fileReader.result as ArrayBuffer);\n    };\n\n    fileReader.onerror = () => {\n      reject(fileReader.error);\n    };\n\n    fileReader.readAsArrayBuffer(file);\n  });\n\nexport const generateFileName = (mimeType: string) =>\n  `file_${new Date().toISOString()}.${getExtensionFromMimeType(mimeType)}`;\n","import { readFileAsArrayBuffer } from '../../ReactFileUtilities';\n\n/**\n * In the context of resampling audio data, AudioContext is used to decode the input audio file into an AudioBuffer,\n * which is a fundamental data structure representing audio data.\n * @param file\n */\nexport const toAudioBuffer = async (file: File) => {\n  const audioCtx = new AudioContext();\n\n  const arrayBuffer = await readFileAsArrayBuffer(file);\n  const decodedData = await audioCtx.decodeAudioData(arrayBuffer);\n  if (audioCtx.state !== 'closed') await audioCtx.close();\n  return decodedData;\n};\n\n/**\n * OfflineAudioContext is a specialized type of AudioContext that does not render audio in real-time and is used for offline audio processing tasks.\n * It allows performing audio processing and rendering without actually playing the audio through speakers or outputting it to a destination.\n * In the context of resampling audio data, OfflineAudioContext is used to resample the decoded AudioBuffer from a file to the desired sample rate.\n * It provides more flexibility and control over audio processing, as it can operate at different sample rates and durations compared to real-time audio contexts.\n * @param audioBuffer\n * @param sampleRate\n */\nexport const renderAudio = async (audioBuffer: AudioBuffer, sampleRate: number) => {\n  const offlineAudioCtx = new OfflineAudioContext(\n    audioBuffer.numberOfChannels,\n    audioBuffer.duration * sampleRate,\n    sampleRate,\n  );\n  const source = offlineAudioCtx.createBufferSource();\n  source.buffer = audioBuffer;\n  source.connect(offlineAudioCtx.destination);\n  source.start();\n\n  return await offlineAudioCtx.startRendering();\n};\n"],"names":[],"mappings":"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"}