@siteed/expo-audio-studio 2.16.0 → 2.17.0

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/CHANGELOG.md CHANGED
@@ -8,6 +8,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
8
  ## [Unreleased]
9
9
 
10
10
 
11
+ ## [2.17.0] - 2025-07-31
12
+ ### Changed
13
+ - fix(expo-audio-studio): fix OutOfMemoryError by tracking stream position correctly ([b67e521](https://github.com/deeeed/expo-audio-stream/commit/b67e52142154d07873c5c1ec9c183d524d61e528))
14
+ - chore(expo-audio-studio): release @siteed/expo-audio-studio@2.16.2 ([c4291a8](https://github.com/deeeed/expo-audio-stream/commit/c4291a82cc740b4d4790c69ae7e7cc07f1e8fb1a))
15
+ ## [2.16.2] - 2025-07-27
16
+ ### Changed
17
+ - chore(expo-audio-studio): release @siteed/expo-audio-studio@2.16.1 ([c9614d4](https://github.com/deeeed/expo-audio-stream/commit/c9614d4ebf87d73c3c5b2f7d6e60492fd5e45e64))
18
+ ## [2.16.1] - 2025-07-27
19
+ ### Changed
20
+ - fix(expo-audio-studio): fix Android audio analysis accumulation showing 0 bytes ([012d478](https://github.com/deeeed/expo-audio-stream/commit/012d478c372db12b9fcf4a49f567d6618eb499f1))
21
+ - chore(expo-audio-studio): release @siteed/expo-audio-studio@2.16.0 ([34c8c0f](https://github.com/deeeed/expo-audio-stream/commit/34c8c0f2f587ecde9adf97c539289b128f0bccc1))
11
22
  ## [2.16.0] - 2025-07-27
12
23
  ### Changed
13
24
  - feat(expo-audio-studio): optimize stop recording performance for long recording on android ([4553dc9](https://github.com/deeeed/expo-audio-stream/commit/4553dc9d2bd101a461f3f2eadfed63114f7d1b22))
@@ -357,7 +368,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
357
368
  - Feature: Audio features extraction during recording.
358
369
  - Feature: Consistent WAV PCM recording format across all platforms.
359
370
 
360
- [unreleased]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-studio@2.16.0...HEAD
371
+ [unreleased]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-studio@2.17.0...HEAD
372
+ [2.17.0]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-studio@2.16.2...@siteed/expo-audio-studio@2.17.0
373
+ [2.16.2]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-studio@2.16.1...@siteed/expo-audio-studio@2.16.2
374
+ [2.16.1]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-studio@2.16.0...@siteed/expo-audio-studio@2.16.1
361
375
  [2.16.0]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-studio@2.15.0...@siteed/expo-audio-studio@2.16.0
362
376
  [2.15.0]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-studio@2.14.9...@siteed/expo-audio-studio@2.15.0
363
377
  [2.14.9]: https://github.com/deeeed/expo-audio-stream/compare/@siteed/expo-audio-studio@2.14.8...@siteed/expo-audio-studio@2.14.9
@@ -77,7 +77,7 @@ class AudioRecorderManager(
77
77
 
78
78
  private var audioRecord: AudioRecord? = null
79
79
  private var bufferSizeInBytes = 0
80
- private var _isRecording = AtomicBoolean(false)
80
+ private val _isRecording = AtomicBoolean(false)
81
81
  private val isPaused = AtomicBoolean(false)
82
82
  private var streamUuid: String? = null
83
83
  private var audioFile: File? = null
@@ -90,6 +90,7 @@ class AudioRecorderManager(
90
90
  private var pausedDuration = 0L
91
91
  private var lastEmittedSize = 0L
92
92
  private var lastEmittedCompressedSize = 0L
93
+ private var streamPosition = 0L // Track total bytes processed in the stream
93
94
  private val mainHandler = Handler(Looper.getMainLooper())
94
95
  private val audioRecordLock = Any()
95
96
  private var audioFileHandler: AudioFileHandler = AudioFileHandler(filesDir)
@@ -378,7 +379,7 @@ class AudioRecorderManager(
378
379
  return deviceDisconnectionBehavior ?: "pause" // Default to pause if not specified
379
380
  }
380
381
 
381
- // Add isRecording property accessor
382
+ // Public property to check if recording is active
382
383
  val isRecording: Boolean
383
384
  get() = _isRecording.get()
384
385
 
@@ -942,6 +943,7 @@ class AudioRecorderManager(
942
943
  val bytesRead = audioRecord?.read(remainingData, 0, bufferSizeInBytes) ?: -1
943
944
  if (bytesRead > 0) {
944
945
  emitAudioData(remainingData.copyOfRange(0, bytesRead), bytesRead)
946
+ streamPosition += bytesRead // Update stream position for final data
945
947
  }
946
948
  }
947
949
 
@@ -966,6 +968,7 @@ class AudioRecorderManager(
966
968
  if (bytesRead > 0) {
967
969
  val emitStartTime = System.currentTimeMillis()
968
970
  emitAudioData(audioData.copyOfRange(0, bytesRead), bytesRead)
971
+ streamPosition += bytesRead // Update stream position for final data
969
972
  }
970
973
 
971
974
  LogUtils.d(CLASS_NAME, "Stopping recording state = ${audioRecord?.state}")
@@ -1403,8 +1406,8 @@ class AudioRecorderManager(
1403
1406
 
1404
1407
  // Initialize timing variables
1405
1408
  var lastEmitTime = System.currentTimeMillis()
1406
- var lastEmissionTimeAnalysis = System.currentTimeMillis()
1407
- var isFirstAnalysis = true
1409
+ lastEmissionTimeAnalysis = System.currentTimeMillis() // Use the class-level variable
1410
+ isFirstAnalysis = true // Use the class-level variable
1408
1411
  var shouldProcessAnalysis = false
1409
1412
 
1410
1413
  // Debug log for intervals
@@ -1420,7 +1423,7 @@ class AudioRecorderManager(
1420
1423
  while (_isRecording.get() && !Thread.currentThread().isInterrupted) {
1421
1424
  loopCount++
1422
1425
  if (loopCount % 100 == 0) {
1423
- LogUtils.d(CLASS_NAME, "Recording loop iteration $loopCount, _isRecording: ${_isRecording.get()}")
1426
+ LogUtils.d(CLASS_NAME, "Recording loop iteration $loopCount, isRecording: ${_isRecording.get()}")
1424
1427
  }
1425
1428
  if (isPaused.get()) {
1426
1429
  Thread.sleep(100) // Add small delay when paused
@@ -1456,6 +1459,11 @@ class AudioRecorderManager(
1456
1459
  totalDataSize += bytesRead
1457
1460
 
1458
1461
  accumulatedAudioData.write(audioData, 0, bytesRead)
1462
+
1463
+ // Also accumulate data for analysis if enabled
1464
+ if (shouldProcessAnalysis) {
1465
+ accumulatedAnalysisData.write(audioData, 0, bytesRead)
1466
+ }
1459
1467
 
1460
1468
  // Handle regular audio data emission
1461
1469
  if (currentTime - lastEmitTime >= recordingConfig.interval) {
@@ -1463,6 +1471,7 @@ class AudioRecorderManager(
1463
1471
  accumulatedAudioData.toByteArray(),
1464
1472
  accumulatedAudioData.size()
1465
1473
  )
1474
+ streamPosition += accumulatedAudioData.size() // Update stream position
1466
1475
  lastEmitTime = currentTime
1467
1476
  accumulatedAudioData.reset() // Clear the accumulator
1468
1477
  }
@@ -1544,9 +1553,15 @@ class AudioRecorderManager(
1544
1553
  val from = lastEmittedSize
1545
1554
  lastEmittedSize = fileSize
1546
1555
 
1547
- // Calculate position in milliseconds
1548
- val positionInMs =
1549
- (from * 1000) / (recordingConfig.sampleRate * recordingConfig.channels * (if (recordingConfig.encoding == "pcm_8bit") 8 else 16) / 8)
1556
+ // Calculate position in milliseconds using stream position
1557
+ val bytesPerSample = when (recordingConfig.encoding) {
1558
+ "pcm_8bit" -> 1
1559
+ "pcm_16bit" -> 2
1560
+ "pcm_32bit" -> 4
1561
+ else -> 2
1562
+ }
1563
+ val byteRate = recordingConfig.sampleRate * recordingConfig.channels * bytesPerSample
1564
+ val positionInMs = (streamPosition * 1000) / byteRate
1550
1565
 
1551
1566
  val compressionBundle = if (recordingConfig.output.compressed.enabled) {
1552
1567
  // For compressed files, we need to get actual size as MediaRecorder handles the writing
@@ -1695,6 +1710,7 @@ class AudioRecorderManager(
1695
1710
  totalRecordedTime = 0
1696
1711
  pausedDuration = 0
1697
1712
  lastEmittedSize = 0
1713
+ streamPosition = 0
1698
1714
  recordingStartTime = 0
1699
1715
 
1700
1716
  // Update the WAV header if needed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@siteed/expo-audio-studio",
3
- "version": "2.16.0",
3
+ "version": "2.17.0",
4
4
  "description": "Comprehensive audio processing library for React Native and Expo with recording, analysis, visualization, and streaming capabilities across iOS, Android, and web",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",