@siteed/expo-audio-studio 2.7.0 → 2.8.1

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.
Files changed (241) hide show
  1. package/CHANGELOG.md +12 -1
  2. package/app.plugin.cjs +15 -2
  3. package/build/cjs/AudioAnalysis/AudioAnalysis.types.js +4 -0
  4. package/build/cjs/AudioAnalysis/AudioAnalysis.types.js.map +1 -0
  5. package/build/cjs/AudioAnalysis/extractAudioAnalysis.js +205 -0
  6. package/build/cjs/AudioAnalysis/extractAudioAnalysis.js.map +1 -0
  7. package/build/cjs/AudioAnalysis/extractAudioData.js +12 -0
  8. package/build/cjs/AudioAnalysis/extractAudioData.js.map +1 -0
  9. package/build/cjs/AudioAnalysis/extractMelSpectrogram.js +89 -0
  10. package/build/cjs/AudioAnalysis/extractMelSpectrogram.js.map +1 -0
  11. package/build/cjs/AudioAnalysis/extractPreview.js +29 -0
  12. package/build/cjs/AudioAnalysis/extractPreview.js.map +1 -0
  13. package/build/cjs/AudioAnalysis/extractWaveform.js +18 -0
  14. package/build/cjs/AudioAnalysis/extractWaveform.js.map +1 -0
  15. package/build/cjs/AudioDeviceManager.js +500 -0
  16. package/build/cjs/AudioDeviceManager.js.map +1 -0
  17. package/build/cjs/AudioRecorder.provider.js +68 -0
  18. package/build/cjs/AudioRecorder.provider.js.map +1 -0
  19. package/build/cjs/ExpoAudioStream.native.js +8 -0
  20. package/build/cjs/ExpoAudioStream.native.js.map +1 -0
  21. package/build/cjs/ExpoAudioStream.types.js +11 -0
  22. package/build/cjs/ExpoAudioStream.types.js.map +1 -0
  23. package/build/cjs/ExpoAudioStream.web.js +705 -0
  24. package/build/cjs/ExpoAudioStream.web.js.map +1 -0
  25. package/build/cjs/ExpoAudioStreamModule.js +718 -0
  26. package/build/cjs/ExpoAudioStreamModule.js.map +1 -0
  27. package/build/cjs/WebRecorder.web.js +756 -0
  28. package/build/cjs/WebRecorder.web.js.map +1 -0
  29. package/build/cjs/constants.js +17 -0
  30. package/build/cjs/constants.js.map +1 -0
  31. package/build/cjs/events.js +30 -0
  32. package/build/cjs/events.js.map +1 -0
  33. package/build/cjs/hooks/useAudioDevices.js +155 -0
  34. package/build/cjs/hooks/useAudioDevices.js.map +1 -0
  35. package/build/cjs/index.js +50 -0
  36. package/build/cjs/index.js.map +1 -0
  37. package/build/cjs/trimAudio.js +75 -0
  38. package/build/cjs/trimAudio.js.map +1 -0
  39. package/build/cjs/useAudioRecorder.js +453 -0
  40. package/build/cjs/useAudioRecorder.js.map +1 -0
  41. package/build/cjs/utils/BlobFix.js +502 -0
  42. package/build/cjs/utils/BlobFix.js.map +1 -0
  43. package/build/cjs/utils/audioProcessing.js +137 -0
  44. package/build/cjs/utils/audioProcessing.js.map +1 -0
  45. package/build/cjs/utils/concatenateBuffers.js +25 -0
  46. package/build/cjs/utils/concatenateBuffers.js.map +1 -0
  47. package/build/cjs/utils/convertPCMToFloat32.js +124 -0
  48. package/build/cjs/utils/convertPCMToFloat32.js.map +1 -0
  49. package/build/cjs/utils/crc32.js +52 -0
  50. package/build/cjs/utils/crc32.js.map +1 -0
  51. package/build/cjs/utils/encodingToBitDepth.js +17 -0
  52. package/build/cjs/utils/encodingToBitDepth.js.map +1 -0
  53. package/build/cjs/utils/getWavFileInfo.js +96 -0
  54. package/build/cjs/utils/getWavFileInfo.js.map +1 -0
  55. package/build/cjs/utils/writeWavHeader.js +88 -0
  56. package/build/cjs/utils/writeWavHeader.js.map +1 -0
  57. package/build/cjs/workers/InlineFeaturesExtractor.web.js +853 -0
  58. package/build/cjs/workers/InlineFeaturesExtractor.web.js.map +1 -0
  59. package/build/cjs/workers/inlineAudioWebWorker.web.js +184 -0
  60. package/build/cjs/workers/inlineAudioWebWorker.web.js.map +1 -0
  61. package/build/esm/AudioAnalysis/AudioAnalysis.types.js.map +1 -0
  62. package/build/esm/AudioAnalysis/extractAudioAnalysis.js.map +1 -0
  63. package/build/esm/AudioAnalysis/extractAudioData.js.map +1 -0
  64. package/build/esm/AudioAnalysis/extractMelSpectrogram.js.map +1 -0
  65. package/build/esm/AudioAnalysis/extractPreview.js.map +1 -0
  66. package/build/esm/AudioAnalysis/extractWaveform.js.map +1 -0
  67. package/build/esm/AudioDeviceManager.js.map +1 -0
  68. package/build/esm/AudioRecorder.provider.js.map +1 -0
  69. package/build/esm/ExpoAudioStream.native.js.map +1 -0
  70. package/build/esm/ExpoAudioStream.types.js.map +1 -0
  71. package/build/esm/ExpoAudioStream.web.js.map +1 -0
  72. package/build/esm/ExpoAudioStreamModule.js.map +1 -0
  73. package/build/esm/WebRecorder.web.js.map +1 -0
  74. package/build/esm/constants.js.map +1 -0
  75. package/build/esm/events.js.map +1 -0
  76. package/build/esm/hooks/useAudioDevices.js.map +1 -0
  77. package/build/esm/index.js.map +1 -0
  78. package/build/esm/trimAudio.js.map +1 -0
  79. package/build/esm/useAudioRecorder.js.map +1 -0
  80. package/build/esm/utils/BlobFix.js.map +1 -0
  81. package/build/esm/utils/audioProcessing.js.map +1 -0
  82. package/build/esm/utils/concatenateBuffers.js.map +1 -0
  83. package/build/esm/utils/convertPCMToFloat32.js.map +1 -0
  84. package/build/esm/utils/crc32.js.map +1 -0
  85. package/build/esm/utils/encodingToBitDepth.js.map +1 -0
  86. package/build/esm/utils/getWavFileInfo.js.map +1 -0
  87. package/build/esm/utils/writeWavHeader.js.map +1 -0
  88. package/build/esm/workers/InlineFeaturesExtractor.web.js.map +1 -0
  89. package/build/esm/workers/inlineAudioWebWorker.web.js.map +1 -0
  90. package/build/types/AudioAnalysis/AudioAnalysis.types.d.ts.map +1 -0
  91. package/build/types/AudioAnalysis/extractAudioAnalysis.d.ts.map +1 -0
  92. package/build/types/AudioAnalysis/extractAudioData.d.ts.map +1 -0
  93. package/build/types/AudioAnalysis/extractMelSpectrogram.d.ts.map +1 -0
  94. package/build/types/AudioAnalysis/extractPreview.d.ts.map +1 -0
  95. package/build/types/AudioAnalysis/extractWaveform.d.ts.map +1 -0
  96. package/build/types/AudioDeviceManager.d.ts.map +1 -0
  97. package/build/types/AudioRecorder.provider.d.ts.map +1 -0
  98. package/build/types/ExpoAudioStream.native.d.ts.map +1 -0
  99. package/build/types/ExpoAudioStream.types.d.ts.map +1 -0
  100. package/build/types/ExpoAudioStream.web.d.ts.map +1 -0
  101. package/build/types/ExpoAudioStreamModule.d.ts.map +1 -0
  102. package/build/types/WebRecorder.web.d.ts.map +1 -0
  103. package/build/types/constants.d.ts.map +1 -0
  104. package/build/types/events.d.ts.map +1 -0
  105. package/build/types/hooks/useAudioDevices.d.ts.map +1 -0
  106. package/build/types/index.d.ts.map +1 -0
  107. package/build/types/trimAudio.d.ts.map +1 -0
  108. package/build/types/useAudioRecorder.d.ts.map +1 -0
  109. package/build/types/utils/BlobFix.d.ts.map +1 -0
  110. package/build/types/utils/audioProcessing.d.ts.map +1 -0
  111. package/build/types/utils/concatenateBuffers.d.ts.map +1 -0
  112. package/build/types/utils/convertPCMToFloat32.d.ts.map +1 -0
  113. package/build/types/utils/crc32.d.ts.map +1 -0
  114. package/build/types/utils/encodingToBitDepth.d.ts.map +1 -0
  115. package/build/types/utils/getWavFileInfo.d.ts.map +1 -0
  116. package/build/types/utils/writeWavHeader.d.ts.map +1 -0
  117. package/build/types/workers/InlineFeaturesExtractor.web.d.ts.map +1 -0
  118. package/build/types/workers/inlineAudioWebWorker.web.d.ts.map +1 -0
  119. package/ios/AudioNotificationManager.swift +42 -19
  120. package/ios/AudioProcessingHelpers.swift +5 -5
  121. package/ios/AudioProcessor.swift +44 -218
  122. package/ios/AudioStreamManager.swift +121 -61
  123. package/ios/DataPoint.swift +5 -5
  124. package/ios/ExpoAudioStreamModule.swift +2 -1
  125. package/package.json +25 -7
  126. package/build/AudioAnalysis/AudioAnalysis.types.d.ts.map +0 -1
  127. package/build/AudioAnalysis/AudioAnalysis.types.js.map +0 -1
  128. package/build/AudioAnalysis/extractAudioAnalysis.d.ts.map +0 -1
  129. package/build/AudioAnalysis/extractAudioAnalysis.js.map +0 -1
  130. package/build/AudioAnalysis/extractAudioData.d.ts.map +0 -1
  131. package/build/AudioAnalysis/extractAudioData.js.map +0 -1
  132. package/build/AudioAnalysis/extractMelSpectrogram.d.ts.map +0 -1
  133. package/build/AudioAnalysis/extractMelSpectrogram.js.map +0 -1
  134. package/build/AudioAnalysis/extractPreview.d.ts.map +0 -1
  135. package/build/AudioAnalysis/extractPreview.js.map +0 -1
  136. package/build/AudioAnalysis/extractWaveform.d.ts.map +0 -1
  137. package/build/AudioAnalysis/extractWaveform.js.map +0 -1
  138. package/build/AudioDeviceManager.d.ts.map +0 -1
  139. package/build/AudioDeviceManager.js.map +0 -1
  140. package/build/AudioRecorder.provider.d.ts.map +0 -1
  141. package/build/AudioRecorder.provider.js.map +0 -1
  142. package/build/ExpoAudioStream.native.d.ts.map +0 -1
  143. package/build/ExpoAudioStream.native.js.map +0 -1
  144. package/build/ExpoAudioStream.types.d.ts.map +0 -1
  145. package/build/ExpoAudioStream.types.js.map +0 -1
  146. package/build/ExpoAudioStream.web.d.ts.map +0 -1
  147. package/build/ExpoAudioStream.web.js.map +0 -1
  148. package/build/ExpoAudioStreamModule.d.ts.map +0 -1
  149. package/build/ExpoAudioStreamModule.js.map +0 -1
  150. package/build/WebRecorder.web.d.ts.map +0 -1
  151. package/build/WebRecorder.web.js.map +0 -1
  152. package/build/constants.d.ts.map +0 -1
  153. package/build/constants.js.map +0 -1
  154. package/build/events.d.ts.map +0 -1
  155. package/build/events.js.map +0 -1
  156. package/build/hooks/useAudioDevices.d.ts.map +0 -1
  157. package/build/hooks/useAudioDevices.js.map +0 -1
  158. package/build/index.d.ts.map +0 -1
  159. package/build/index.js.map +0 -1
  160. package/build/trimAudio.d.ts.map +0 -1
  161. package/build/trimAudio.js.map +0 -1
  162. package/build/useAudioRecorder.d.ts.map +0 -1
  163. package/build/useAudioRecorder.js.map +0 -1
  164. package/build/utils/BlobFix.d.ts.map +0 -1
  165. package/build/utils/BlobFix.js.map +0 -1
  166. package/build/utils/audioProcessing.d.ts.map +0 -1
  167. package/build/utils/audioProcessing.js.map +0 -1
  168. package/build/utils/concatenateBuffers.d.ts.map +0 -1
  169. package/build/utils/concatenateBuffers.js.map +0 -1
  170. package/build/utils/convertPCMToFloat32.d.ts.map +0 -1
  171. package/build/utils/convertPCMToFloat32.js.map +0 -1
  172. package/build/utils/crc32.d.ts.map +0 -1
  173. package/build/utils/crc32.js.map +0 -1
  174. package/build/utils/encodingToBitDepth.d.ts.map +0 -1
  175. package/build/utils/encodingToBitDepth.js.map +0 -1
  176. package/build/utils/getWavFileInfo.d.ts.map +0 -1
  177. package/build/utils/getWavFileInfo.js.map +0 -1
  178. package/build/utils/writeWavHeader.d.ts.map +0 -1
  179. package/build/utils/writeWavHeader.js.map +0 -1
  180. package/build/workers/InlineFeaturesExtractor.web.d.ts.map +0 -1
  181. package/build/workers/InlineFeaturesExtractor.web.js.map +0 -1
  182. package/build/workers/inlineAudioWebWorker.web.d.ts.map +0 -1
  183. package/build/workers/inlineAudioWebWorker.web.js.map +0 -1
  184. /package/build/{AudioAnalysis → esm/AudioAnalysis}/AudioAnalysis.types.js +0 -0
  185. /package/build/{AudioAnalysis → esm/AudioAnalysis}/extractAudioAnalysis.js +0 -0
  186. /package/build/{AudioAnalysis → esm/AudioAnalysis}/extractAudioData.js +0 -0
  187. /package/build/{AudioAnalysis → esm/AudioAnalysis}/extractMelSpectrogram.js +0 -0
  188. /package/build/{AudioAnalysis → esm/AudioAnalysis}/extractPreview.js +0 -0
  189. /package/build/{AudioAnalysis → esm/AudioAnalysis}/extractWaveform.js +0 -0
  190. /package/build/{AudioDeviceManager.js → esm/AudioDeviceManager.js} +0 -0
  191. /package/build/{AudioRecorder.provider.js → esm/AudioRecorder.provider.js} +0 -0
  192. /package/build/{ExpoAudioStream.native.js → esm/ExpoAudioStream.native.js} +0 -0
  193. /package/build/{ExpoAudioStream.types.js → esm/ExpoAudioStream.types.js} +0 -0
  194. /package/build/{ExpoAudioStream.web.js → esm/ExpoAudioStream.web.js} +0 -0
  195. /package/build/{ExpoAudioStreamModule.js → esm/ExpoAudioStreamModule.js} +0 -0
  196. /package/build/{WebRecorder.web.js → esm/WebRecorder.web.js} +0 -0
  197. /package/build/{constants.js → esm/constants.js} +0 -0
  198. /package/build/{events.js → esm/events.js} +0 -0
  199. /package/build/{hooks → esm/hooks}/useAudioDevices.js +0 -0
  200. /package/build/{index.js → esm/index.js} +0 -0
  201. /package/build/{trimAudio.js → esm/trimAudio.js} +0 -0
  202. /package/build/{useAudioRecorder.js → esm/useAudioRecorder.js} +0 -0
  203. /package/build/{utils → esm/utils}/BlobFix.js +0 -0
  204. /package/build/{utils → esm/utils}/audioProcessing.js +0 -0
  205. /package/build/{utils → esm/utils}/concatenateBuffers.js +0 -0
  206. /package/build/{utils → esm/utils}/convertPCMToFloat32.js +0 -0
  207. /package/build/{utils → esm/utils}/crc32.js +0 -0
  208. /package/build/{utils → esm/utils}/encodingToBitDepth.js +0 -0
  209. /package/build/{utils → esm/utils}/getWavFileInfo.js +0 -0
  210. /package/build/{utils → esm/utils}/writeWavHeader.js +0 -0
  211. /package/build/{workers → esm/workers}/InlineFeaturesExtractor.web.js +0 -0
  212. /package/build/{workers → esm/workers}/inlineAudioWebWorker.web.js +0 -0
  213. /package/build/{AudioAnalysis → types/AudioAnalysis}/AudioAnalysis.types.d.ts +0 -0
  214. /package/build/{AudioAnalysis → types/AudioAnalysis}/extractAudioAnalysis.d.ts +0 -0
  215. /package/build/{AudioAnalysis → types/AudioAnalysis}/extractAudioData.d.ts +0 -0
  216. /package/build/{AudioAnalysis → types/AudioAnalysis}/extractMelSpectrogram.d.ts +0 -0
  217. /package/build/{AudioAnalysis → types/AudioAnalysis}/extractPreview.d.ts +0 -0
  218. /package/build/{AudioAnalysis → types/AudioAnalysis}/extractWaveform.d.ts +0 -0
  219. /package/build/{AudioDeviceManager.d.ts → types/AudioDeviceManager.d.ts} +0 -0
  220. /package/build/{AudioRecorder.provider.d.ts → types/AudioRecorder.provider.d.ts} +0 -0
  221. /package/build/{ExpoAudioStream.native.d.ts → types/ExpoAudioStream.native.d.ts} +0 -0
  222. /package/build/{ExpoAudioStream.types.d.ts → types/ExpoAudioStream.types.d.ts} +0 -0
  223. /package/build/{ExpoAudioStream.web.d.ts → types/ExpoAudioStream.web.d.ts} +0 -0
  224. /package/build/{ExpoAudioStreamModule.d.ts → types/ExpoAudioStreamModule.d.ts} +0 -0
  225. /package/build/{WebRecorder.web.d.ts → types/WebRecorder.web.d.ts} +0 -0
  226. /package/build/{constants.d.ts → types/constants.d.ts} +0 -0
  227. /package/build/{events.d.ts → types/events.d.ts} +0 -0
  228. /package/build/{hooks → types/hooks}/useAudioDevices.d.ts +0 -0
  229. /package/build/{index.d.ts → types/index.d.ts} +0 -0
  230. /package/build/{trimAudio.d.ts → types/trimAudio.d.ts} +0 -0
  231. /package/build/{useAudioRecorder.d.ts → types/useAudioRecorder.d.ts} +0 -0
  232. /package/build/{utils → types/utils}/BlobFix.d.ts +0 -0
  233. /package/build/{utils → types/utils}/audioProcessing.d.ts +0 -0
  234. /package/build/{utils → types/utils}/concatenateBuffers.d.ts +0 -0
  235. /package/build/{utils → types/utils}/convertPCMToFloat32.d.ts +0 -0
  236. /package/build/{utils → types/utils}/crc32.d.ts +0 -0
  237. /package/build/{utils → types/utils}/encodingToBitDepth.d.ts +0 -0
  238. /package/build/{utils → types/utils}/getWavFileInfo.d.ts +0 -0
  239. /package/build/{utils → types/utils}/writeWavHeader.d.ts +0 -0
  240. /package/build/{workers → types/workers}/InlineFeaturesExtractor.web.d.ts +0 -0
  241. /package/build/{workers → types/workers}/inlineAudioWebWorker.web.d.ts +0 -0
@@ -37,43 +37,66 @@ class AudioNotificationManager {
37
37
  }
38
38
 
39
39
  func showInitialNotification() {
40
- updateNotification()
40
+ // Wrap notification generation in a main thread dispatch
41
+ DispatchQueue.main.async { [weak self] in
42
+ guard let self = self else { return }
43
+
44
+ // No need for try-catch as this method doesn't throw
45
+ self.updateNotification()
46
+ }
41
47
  }
42
48
 
43
49
  func startUpdates(startTime: Date) {
44
- DispatchQueue.main.async {
45
- self.updateTimer?.invalidate()
50
+ // Cancel any existing timer first
51
+ stopUpdates()
52
+
53
+ // Create a new timer on the main thread
54
+ DispatchQueue.main.async { [weak self] in
55
+ guard let self = self else { return }
46
56
 
47
57
  self.updateTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in
48
58
  guard let self = self else { return }
49
-
50
- let now = Date()
51
- if now.timeIntervalSince(self.lastUpdateTime) >= self.minUpdateInterval {
52
- self.updateNotification()
53
- self.lastUpdateTime = now
54
- }
59
+ self.currentDuration = Date().timeIntervalSince(startTime)
60
+ self.updateState(isPaused: false)
55
61
  }
56
- RunLoop.main.add(self.updateTimer!, forMode: .common)
57
62
 
58
- self.showInitialNotification()
63
+ // Run the timer even when scrolling
64
+ self.updateTimer?.tolerance = 0.1
65
+ RunLoop.current.add(self.updateTimer!, forMode: .common)
66
+
67
+ // Update notification immediately
68
+ self.updateState(isPaused: false)
59
69
  }
60
70
  }
61
71
 
62
72
  func stopUpdates() {
63
- DispatchQueue.main.async {
73
+ // Always execute timer invalidation on main thread
74
+ DispatchQueue.main.async { [weak self] in
75
+ guard let self = self else { return }
76
+
64
77
  self.updateTimer?.invalidate()
65
78
  self.updateTimer = nil
66
79
 
67
- self.notificationCenter.removeDeliveredNotifications(withIdentifiers: [self.notificationId])
68
- self.notificationCenter.removePendingNotificationRequests(withIdentifiers: [self.notificationId])
80
+ // Clean up notification
81
+ do {
82
+ self.notificationCenter.removeDeliveredNotifications(withIdentifiers: [self.notificationId])
83
+ self.notificationCenter.removePendingNotificationRequests(withIdentifiers: [self.notificationId])
84
+ } catch {
85
+ Logger.debug("AudioNotificationManager", "Error removing notifications: \(error)")
86
+ }
69
87
  }
70
88
  }
71
89
 
72
90
  func updateState(isPaused: Bool) {
73
- let now = Date()
74
- if now.timeIntervalSince(lastUpdateTime) >= minUpdateInterval {
75
- updateNotification(forcePauseState: isPaused)
76
- lastUpdateTime = now
91
+ DispatchQueue.main.async { [weak self] in
92
+ guard let self = self else { return }
93
+
94
+ let now = Date()
95
+ if now.timeIntervalSince(self.lastUpdateTime) >= self.minUpdateInterval {
96
+ // No need for try-catch as this method doesn't throw
97
+ self.updateNotification(forcePauseState: isPaused)
98
+ self.lastUpdateTime = now
99
+ }
77
100
  }
78
101
  }
79
102
 
@@ -92,7 +115,7 @@ class AudioNotificationManager {
92
115
  guard let self = self else { return }
93
116
 
94
117
  // If we have a notification and it was recently updated, skip
95
- if let existing = notifications.first(where: { $0.request.identifier == self.notificationId }),
118
+ if let _ = notifications.first(where: { $0.request.identifier == self.notificationId }),
96
119
  Date().timeIntervalSince(self.lastUpdateTime) < self.minUpdateInterval {
97
120
  return
98
121
  }
@@ -337,7 +337,6 @@ func computeMelSpectrogram(from segment: [Float], sampleRate: Float) -> [Float]
337
337
  }
338
338
 
339
339
  func computeSpectralContrast(from segment: [Float], sampleRate: Float) -> [Float] {
340
- let nBands = 7
341
340
  let fftData = sharedFFT.processSegment(segment)
342
341
 
343
342
  let magnitudeSpectrum = computeMagnitudeSpectrum(from: fftData)
@@ -425,7 +424,7 @@ func loadAudioFile(_ fileUri: String) throws -> AudioData {
425
424
  let frameCount = UInt32(file.length)
426
425
  let buffer = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: frameCount)!
427
426
 
428
- try file.read(into: buffer)
427
+ try file.read(into: buffer, frameCount: frameCount)
429
428
 
430
429
  // Convert buffer to float array
431
430
  let samples: [Float]
@@ -490,8 +489,8 @@ func computeFeatures(segmentData: [Float], sampleRate: Float, sumSquares: Float,
490
489
  let zcr = featureOptions["zcr"] == true ? Float(zeroCrossings) / Float(segmentLength) : 0
491
490
 
492
491
  // Compute min and max amplitudes
493
- let minAmplitude = segmentData.min() ?? 0
494
- let maxAmplitude = segmentData.max() ?? 0
492
+ let _ = segmentData.min() ?? 0
493
+ let _ = segmentData.max() ?? 0
495
494
 
496
495
  // Call feature extraction functions
497
496
  let mfcc = featureOptions["mfcc"] == true ? extractMFCC(from: segmentData, sampleRate: sampleRate) : []
@@ -598,12 +597,13 @@ func extractRawAudioData(
598
597
  finalBuffer = AVAudioPCMBuffer(pcmFormat: targetFormat, frameCapacity: frameCount)!
599
598
 
600
599
  var error: NSError?
601
- let status = converter.convert(to: finalBuffer, error: &error) { inNumPackets, outStatus in
600
+ _ = converter.convert(to: finalBuffer, error: &error) { inNumPackets, outStatus in
602
601
  outStatus.pointee = .haveData
603
602
  return buffer
604
603
  }
605
604
 
606
605
  if let error = error {
606
+ Logger.debug("AudioProcessingHelpers", "Format conversion failed: \(error.localizedDescription)")
607
607
  throw error
608
608
  }
609
609
  } else {
@@ -142,7 +142,7 @@ public class AudioProcessor {
142
142
 
143
143
  let totalFrameCount = AVAudioFrameCount(audioFile.length)
144
144
  var framesPerBuffer: AVAudioFrameCount
145
- let actualPointsPerSecond: Int
145
+ let _: Int // Changed from actualPointsPerSecond
146
146
 
147
147
  NSLog("""
148
148
  [AudioProcessor] Starting audio processing:
@@ -215,7 +215,7 @@ public class AudioProcessor {
215
215
  }
216
216
 
217
217
  channelCount = Int(audioFile.processingFormat.channelCount)
218
- var data = Array(repeating: [Float](repeating: 0, count: Int(framesPerBuffer)), count: channelCount)
218
+ let _ = Array(repeating: [Float](repeating: 0, count: Int(framesPerBuffer)), count: channelCount) // Changed from var data
219
219
 
220
220
  var channelData = [Float]()
221
221
  while startFrame < endFrame {
@@ -517,7 +517,7 @@ public class AudioProcessor {
517
517
 
518
518
  let startTime = CACurrentMediaTime()
519
519
  let sampleRate = Float(audioFile.fileFormat.sampleRate)
520
- let totalFrameCount = AVAudioFrameCount(audioFile.length)
520
+ let _ = AVAudioFrameCount(audioFile.length) // Changed from totalFrameCount
521
521
  let bitDepth = audioFile.fileFormat.settings[AVLinearPCMBitDepthKey] as? Int ?? 16
522
522
  let numberOfChannels = Int(audioFile.fileFormat.channelCount)
523
523
 
@@ -595,7 +595,7 @@ public class AudioProcessor {
595
595
  dB: Float(20 * log10(Double(rms))), // Use RMS for dB calculation
596
596
  silent: rms < SILENCE_THRESHOLD_RMS, // Use RMS for silence detection
597
597
  features: computeFeatures(
598
- segmentData: Array(UnsafeBufferPointer(start: summedData, count: Int(framesToRead))),
598
+ segmentData: Array(summedData[0..<Int(framesToRead)]), // Fixed dangling pointer
599
599
  sampleRate: sampleRate,
600
600
  sumSquares: rms * rms,
601
601
  zeroCrossings: 0,
@@ -692,7 +692,7 @@ public class AudioProcessor {
692
692
 
693
693
  // Output format setup
694
694
  let requestedFormat = outputFormat?["format"] as? String ?? "wav"
695
- let validFormats = ["wav", "aac", "opus"]
695
+ let validFormats = ["wav", "aac"]
696
696
  let formatStr = validFormats.contains(requestedFormat.lowercased()) ? requestedFormat.lowercased() : "aac"
697
697
 
698
698
  if formatStr != requestedFormat.lowercased() {
@@ -704,7 +704,7 @@ public class AudioProcessor {
704
704
  let targetBitDepth = outputFormat?["bitDepth"] as? Int ?? 16
705
705
  let bitrate = outputFormat?["bitrate"] as? Int ?? 128000
706
706
 
707
- let fileExtension = formatStr == "wav" ? "wav" : (formatStr == "aac" ? "aac" : "opus")
707
+ let fileExtension = formatStr == "wav" ? "wav" : "aac"
708
708
  let outputURL = FileManager.default.temporaryDirectory
709
709
  .appendingPathComponent(outputFileName ?? UUID().uuidString)
710
710
  .appendingPathExtension(fileExtension)
@@ -753,7 +753,7 @@ public class AudioProcessor {
753
753
  Logger.debug("AudioProcessor", "Trim operation completed")
754
754
  Logger.debug("AudioProcessor", "- Output file: \(outputURL.path)")
755
755
  Logger.debug("AudioProcessor", "- File exists: \(FileManager.default.fileExists(atPath: outputURL.path))")
756
- Logger.debug("AudioProcessor", "- File size: \(try? FileManager.default.attributesOfItem(atPath: outputURL.path)[.size] as? Int64 ?? 0) bytes")
756
+ Logger.debug("AudioProcessor", "- File size: \((try? FileManager.default.attributesOfItem(atPath: outputURL.path)[.size] as? Int64) ?? 0) bytes") // Fixed optional unwrapping
757
757
  Logger.debug("AudioProcessor", "- File extension: \(outputURL.pathExtension)")
758
758
 
759
759
  return createTrimResult(from: outputURL, keepRanges: keepRanges, formatStr: formatStr, sampleRate: Int(inputSampleRate), channels: inputChannels, bitDepth: 16, bitrate: bitrate)
@@ -808,8 +808,8 @@ public class AudioProcessor {
808
808
  }
809
809
  if let error = error {
810
810
  Logger.debug("AudioProcessor", "Format conversion failed: \(error.localizedDescription)")
811
- reject("CONVERSION_ERROR", "Failed to convert audio format: \(error.localizedDescription)")
812
- return nil
811
+ Logger.debug("AudioProcessor", "Skipping this buffer")
812
+ continue
813
813
  }
814
814
  try outputFile.write(from: convertedBuffer)
815
815
  cumulativeFrames += Int64(frameCount)
@@ -818,227 +818,53 @@ public class AudioProcessor {
818
818
  }
819
819
  return createTrimResult(from: outputURL, keepRanges: keepRanges, formatStr: formatStr, sampleRate: Int(targetSampleRate), channels: targetChannels, bitDepth: targetBitDepth, bitrate: bitrate)
820
820
  } else {
821
- // AAC or Opus output
822
- let outputSettings: [String: Any]
823
- let fileType: AVFileType
821
+ // Use AAC instead of Opus (Opus support removed)
822
+ Logger.debug("AudioProcessor", "Using AAC format instead of requested \(formatStr)")
824
823
 
825
- if formatStr == "aac" {
826
- // AAC settings
827
- let outputExtension = "m4a"
828
- let tempOutputURL = FileManager.default.temporaryDirectory
829
- .appendingPathComponent(outputFileName ?? UUID().uuidString)
830
- .appendingPathExtension(outputExtension)
831
-
832
- // Validate and adjust sample rate for AAC
833
- // AAC typically supports: 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 Hz
834
- let supportedSampleRates = [8000.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0, 44100.0, 48000.0]
835
-
836
- // Default to 44100 if not specified
837
- var sampleRate = outputFormat?["sampleRate"] as? Double ?? 44100.0
838
-
839
- // Find closest supported sample rate
840
- if !supportedSampleRates.contains(sampleRate) {
841
- let closestRate = supportedSampleRates.min(by: { abs($0 - sampleRate) < abs($1 - sampleRate) }) ?? 44100.0
842
- Logger.debug("AudioProcessor", "Unsupported sample rate \(sampleRate)Hz for AAC, using closest supported rate: \(closestRate)Hz")
843
- sampleRate = closestRate
844
- }
845
-
846
- // Validate channels (AAC typically supports 1 or 2 channels)
847
- var channels = outputFormat?["channels"] as? Int ?? 2
848
- if channels > 2 {
849
- Logger.debug("AudioProcessor", "AAC encoding doesn't support \(channels) channels, limiting to 2 channels")
850
- channels = 2
851
- } else if channels < 1 {
852
- channels = 1
853
- }
854
-
855
- // Validate bitrate (AAC typically supports 8000-320000 bps)
856
- var bitrate = outputFormat?["bitrate"] as? Int ?? 128000
857
- if bitrate < 8000 {
858
- Logger.debug("AudioProcessor", "AAC bitrate too low, setting to minimum 8000 bps")
859
- bitrate = 8000
860
- } else if bitrate > 320000 {
861
- Logger.debug("AudioProcessor", "AAC bitrate too high, setting to maximum 320000 bps")
862
- bitrate = 320000
863
- }
864
-
865
- // Set up proper audio settings for AAC
866
- outputSettings = [
867
- AVFormatIDKey: kAudioFormatMPEG4AAC,
868
- AVSampleRateKey: sampleRate,
869
- AVNumberOfChannelsKey: channels,
870
- AVEncoderBitRateKey: bitrate,
871
- AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
872
- ]
873
- fileType = .m4a
874
-
875
- Logger.debug("AudioProcessor", """
876
- Configuring AAC output:
877
- - Container: m4a
878
- - Format: AAC
879
- - Sample rate: \(sampleRate)Hz
880
- - Channels: \(channels)
881
- - Bitrate: \(bitrate) bps
882
- - Output path: \(tempOutputURL.path)
883
- - File type: \(fileType)
884
- """)
885
- } else {
886
- // Opus settings - use CAF container which can hold Opus
887
- outputSettings = [
888
- AVFormatIDKey: kAudioFormatOpus,
889
- AVSampleRateKey: targetSampleRate,
890
- AVNumberOfChannelsKey: targetChannels,
891
- AVEncoderBitRateKey: bitrate
892
- ]
893
- fileType = .caf // Core Audio Format can contain Opus
894
- }
895
-
896
- // Use proper file extension for the container format
897
- let tempFileExtension = formatStr == "aac" ? "m4a" : "caf"
898
- let tempOutputURL = FileManager.default.temporaryDirectory
899
- .appendingPathComponent(outputFileName ?? UUID().uuidString)
900
- .appendingPathExtension(tempFileExtension)
901
-
902
- // Create the asset writer with the appropriate file type
903
- let assetWriter = try AVAssetWriter(
904
- outputURL: tempOutputURL,
905
- fileType: fileType
906
- )
824
+ // Keep the existing AAC settings structure for consistency
825
+ let outputSettings: [String: Any] = [
826
+ AVFormatIDKey: kAudioFormatMPEG4AAC,
827
+ AVSampleRateKey: targetSampleRate,
828
+ AVNumberOfChannelsKey: targetChannels,
829
+ AVEncoderBitRateKey: bitrate,
830
+ AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
831
+ ]
832
+ let _ = AVFileType.m4a // Changed from fileType
907
833
 
908
- // Configure the writer input with better settings
909
- let writerInput = AVAssetWriterInput(mediaType: .audio, outputSettings: outputSettings)
910
- writerInput.expectsMediaDataInRealTime = false
911
- assetWriter.add(writerInput)
834
+ // 4. Update container extension logic for when Opus was selected
835
+ let _ = "m4a" // Changed from tempFileExtension
912
836
 
913
- // Start the writing session
914
- assetWriter.startWriting()
915
- assetWriter.startSession(atSourceTime: CMTime.zero)
837
+ // 5. Update the MIME type logic for AAC only
838
+ let _ = "audio/mp4" // Changed from mimeType
916
839
 
917
- // Improved buffer handling
918
- let bufferSize = 32768 // Use a larger buffer for better performance
919
- let pcmBuffer = AVAudioPCMBuffer(pcmFormat: targetFormat, frameCapacity: AVAudioFrameCount(bufferSize))!
920
-
840
+ let outputFile = try AVAudioFile(forWriting: outputURL, settings: outputSettings)
841
+ var totalFrames: Int64 = 0
921
842
  for range in keepRanges {
843
+ // Break down complex expressions
922
844
  let startTimeInSeconds = range[0] / 1000
923
845
  let startFrame = AVAudioFramePosition(startTimeInSeconds * inputSampleRate)
924
846
 
925
847
  let endTimeInSeconds = range[1] / 1000
926
848
  let endFramePosition = endTimeInSeconds * inputSampleRate
927
- let totalFramesToProcess = AVAudioFrameCount(endFramePosition - Double(startFrame))
849
+ let frameCount = AVAudioFrameCount(endFramePosition - Double(startFrame))
928
850
 
929
- // Process in chunks for better memory management
930
- var framesProcessed: AVAudioFrameCount = 0
851
+ let buffer = AVAudioPCMBuffer(pcmFormat: inputFormat, frameCapacity: frameCount)!
931
852
  audioFile.framePosition = startFrame
932
-
933
- while framesProcessed < totalFramesToProcess {
934
- let framesToRead = min(AVAudioFrameCount(bufferSize), totalFramesToProcess - framesProcessed)
935
- let buffer = AVAudioPCMBuffer(pcmFormat: inputFormat, frameCapacity: framesToRead)!
936
-
937
- do {
938
- try audioFile.read(into: buffer, frameCount: framesToRead)
939
-
940
- // Convert the buffer to the target format
941
- let converter = AVAudioConverter(from: inputFormat, to: targetFormat)!
942
- let convertedBuffer = AVAudioPCMBuffer(pcmFormat: targetFormat, frameCapacity: framesToRead)!
943
-
944
- var error: NSError?
945
- _ = converter.convert(to: convertedBuffer, error: &error) { inNumPackets, outStatus in
946
- outStatus.pointee = .haveData
947
- return buffer
948
- }
949
-
950
- if let error = error {
951
- Logger.debug("AudioProcessor", "Conversion error: \(error)")
952
- continue
953
- }
954
-
955
- // Create a sample buffer and append to writer
956
- if let sampleBuffer = createSampleBuffer(from: convertedBuffer) {
957
- // Wait until the writer is ready
958
- while !writerInput.isReadyForMoreMediaData {
959
- Thread.sleep(forTimeInterval: 0.01)
960
- }
961
-
962
- if !writerInput.append(sampleBuffer) {
963
- Logger.debug("AudioProcessor", "Failed to append sample buffer: \(assetWriter.error?.localizedDescription ?? "Unknown error")")
964
- }
965
- }
966
-
967
- framesProcessed += framesToRead
968
- cumulativeFrames += Int64(framesToRead)
969
- let progress = Float(cumulativeFrames) / Float(totalFrames) * 100
970
- progressCallback?(progress, 0, totalFrames * Int64(inputFormat.streamDescription.pointee.mBytesPerFrame))
971
-
972
- if framesProcessed % 10000 == 0 { // Log every 10000 frames to avoid excessive logging
973
- Logger.debug("AudioProcessor", "Processed \(framesProcessed)/\(totalFramesToProcess) frames")
974
- }
975
-
976
- } catch {
977
- Logger.debug("AudioProcessor", "Error reading audio: \(error)")
978
- break
979
- }
980
- }
981
- }
982
-
983
- // Finish writing properly
984
- writerInput.markAsFinished()
985
- let finishSemaphore = DispatchSemaphore(value: 0)
986
- assetWriter.finishWriting {
987
- if let error = assetWriter.error {
988
- Logger.debug("AudioProcessor", "Error finishing writing: \(error)")
989
- } else {
990
- Logger.debug("AudioProcessor", "Writing finished successfully")
991
-
992
- // Verify the output file
993
- let fileExists = FileManager.default.fileExists(atPath: tempOutputURL.path)
994
- let fileSize = (try? FileManager.default.attributesOfItem(atPath: tempOutputURL.path)[.size] as? Int64) ?? 0
995
-
996
- Logger.debug("AudioProcessor", """
997
- Output file verification:
998
- - Path: \(tempOutputURL.path)
999
- - Exists: \(fileExists)
1000
- - Size: \(fileSize) bytes
1001
- - Extension: \(tempOutputURL.pathExtension)
1002
- """)
1003
- }
1004
- finishSemaphore.signal()
1005
- }
1006
- finishSemaphore.wait()
1007
-
1008
- // Verify the file was created successfully
1009
- guard FileManager.default.fileExists(atPath: tempOutputURL.path) else {
1010
- reject("FILE_CREATION_FAILED", "Failed to create output file")
1011
- return nil
1012
- }
1013
-
1014
- // Create compression info
1015
- var compressionInfo: [String: Any] = [
1016
- "format": formatStr,
1017
- "bitrate": bitrate,
1018
- "size": (try? FileManager.default.attributesOfItem(atPath: tempOutputURL.path)[.size] as? Int64) ?? 0
1019
- ]
1020
-
1021
- // Add fallback information if applicable
1022
- if formatStr != requestedFormat.lowercased() {
1023
- compressionInfo["requestedFormat"] = requestedFormat
1024
- compressionInfo["fallbackReason"] = "Unsupported format"
853
+ try audioFile.read(into: buffer, frameCount: frameCount)
854
+ try outputFile.write(from: buffer)
855
+ totalFrames += Int64(frameCount)
856
+ let progress = Float(cumulativeFrames) / Float(totalFrames) * 100
857
+ progressCallback?(progress, 0, totalFrames * Int64(inputFormat.streamDescription.pointee.mBytesPerFrame))
1025
858
  }
1026
-
1027
- // Use the correct MIME type
1028
- let mimeType = formatStr == "aac" ? "audio/mp4" : "audio/opus"
1029
-
1030
- return TrimResult(
1031
- uri: tempOutputURL.absoluteString,
1032
- filename: tempOutputURL.lastPathComponent,
1033
- durationMs: keepRanges.map { $0[1] - $0[0] }.reduce(0, +),
1034
- size: (try? FileManager.default.attributesOfItem(atPath: tempOutputURL.path)[.size] as? Int64) ?? 0,
1035
- sampleRate: Int(targetSampleRate),
1036
- channels: targetChannels,
1037
- bitDepth: 16,
1038
- mimeType: mimeType,
1039
- requestedFormat: formatStr,
1040
- actualFormat: tempFileExtension,
1041
- compression: compressionInfo
859
+ return createTrimResult(
860
+ from: outputURL,
861
+ keepRanges: keepRanges,
862
+ formatStr: formatStr,
863
+ sampleRate: Int(targetSampleRate),
864
+ channels: targetChannels,
865
+ bitDepth: 16,
866
+ bitrate: bitrate,
867
+ compression: nil
1042
868
  )
1043
869
  }
1044
870
  }
@@ -1077,7 +903,7 @@ public class AudioProcessor {
1077
903
  private func createTrimResult(from url: URL, keepRanges: [[Double]], formatStr: String, sampleRate: Int, channels: Int, bitDepth: Int, bitrate: Int, compression: [String: Any]? = nil) -> TrimResult {
1078
904
  let durationMs = keepRanges.map { $0[1] - $0[0] }.reduce(0, +)
1079
905
  let size = (try? FileManager.default.attributesOfItem(atPath: url.path)[.size] as? Int64 ?? 0) ?? 0
1080
- let fileExtension = formatStr == "wav" ? "wav" : (formatStr == "aac" ? "aac" : "opus")
906
+ let fileExtension = formatStr == "wav" ? "wav" : "aac"
1081
907
  return TrimResult(
1082
908
  uri: url.absoluteString,
1083
909
  filename: url.lastPathComponent,