Add console logs.
This commit is contained in:
		| @@ -42,6 +42,7 @@ import dev.adriankuta.visualizer.components.MetricsSection | ||||
| import dev.adriankuta.visualizer.components.PermissionSection | ||||
| import dev.adriankuta.visualizer.components.WaveformView | ||||
| import dev.adriankuta.visualizer.ui.theme.VisualizerTheme | ||||
| import timber.log.Timber | ||||
|  | ||||
| /** | ||||
|  * Entry point activity that hosts the Compose UI for the audio visualizer demo. | ||||
| @@ -51,6 +52,10 @@ import dev.adriankuta.visualizer.ui.theme.VisualizerTheme | ||||
| class MainActivity : ComponentActivity() { | ||||
|     override fun onCreate(savedInstanceState: Bundle?) { | ||||
|         super.onCreate(savedInstanceState) | ||||
|  | ||||
|         // Initialize Timber for logging | ||||
|         Timber.plant(Timber.DebugTree()) | ||||
|  | ||||
|         enableEdgeToEdge() | ||||
|         setContent { | ||||
|             VisualizerTheme { | ||||
| @@ -103,8 +108,8 @@ private fun VisualizerScreen(modifier: Modifier = Modifier) { | ||||
|         val observer = LifecycleEventObserver { _, event -> | ||||
|             if (!permissionGranted) return@LifecycleEventObserver | ||||
|             when (event) { | ||||
|                 Lifecycle.Event.ON_START -> runCatching { controller.start() } | ||||
|                 Lifecycle.Event.ON_STOP -> runCatching { controller.stop() } | ||||
|                 Lifecycle.Event.ON_CREATE -> runCatching { controller.start() } | ||||
|                 Lifecycle.Event.ON_DESTROY -> runCatching { controller.stop() } | ||||
|                 else -> {} | ||||
|             } | ||||
|         } | ||||
| @@ -179,4 +184,4 @@ fun VisualizerPreview() { | ||||
|     VisualizerTheme { | ||||
|         VisualizerScreen() | ||||
|     } | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,8 @@ | ||||
| package dev.adriankuta.visualizer | ||||
|  | ||||
| import android.media.audiofx.Visualizer | ||||
| import kotlinx.coroutines.* | ||||
| import timber.log.Timber | ||||
|  | ||||
| /** | ||||
|  * Simple wrapper over Android Visualizer to capture global output mix (audio session 0). | ||||
| @@ -11,6 +13,10 @@ class VisualizerController( | ||||
|     private val onFft: (ByteArray) -> Unit, | ||||
| ) { | ||||
|     private var visualizer: Visualizer? = null | ||||
|     private val coroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob()) | ||||
|     private var loggingJob: Job? = null | ||||
|     private var latestWaveform: ByteArray? = null | ||||
|     private var latestFft: ByteArray? = null | ||||
|  | ||||
|     /** | ||||
|      * Starts capturing audio data via [Visualizer]. | ||||
| @@ -23,6 +29,7 @@ class VisualizerController( | ||||
|     fun start() { | ||||
|         if (visualizer != null) return | ||||
|         try { | ||||
|             Timber.d("Starting audio visualizer listening (audioSessionId: $audioSessionId)") | ||||
|             val v = Visualizer(audioSessionId) | ||||
|             // Use the maximum supported capture size for better resolution | ||||
|             val captureSize = Visualizer.getCaptureSizeRange().let { it[1] } | ||||
| @@ -34,7 +41,10 @@ class VisualizerController( | ||||
|                     waveform: ByteArray?, | ||||
|                     samplingRate: Int | ||||
|                 ) { | ||||
|                     if (waveform != null) onWaveform(waveform) | ||||
|                     if (waveform != null) { | ||||
|                         latestWaveform = waveform.clone() | ||||
|                         onWaveform(waveform) | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 override fun onFftDataCapture( | ||||
| @@ -42,13 +52,22 @@ class VisualizerController( | ||||
|                     fft: ByteArray?, | ||||
|                     samplingRate: Int | ||||
|                 ) { | ||||
|                     if (fft != null) onFft(fft) | ||||
|                     if (fft != null) { | ||||
|                         latestFft = fft.clone() | ||||
|                         onFft(fft) | ||||
|                     } | ||||
|                 } | ||||
|             }, rate, true, true) | ||||
|             v.enabled = true | ||||
|             visualizer = v | ||||
|  | ||||
|             // Start coroutine-based logging for raw data samples every 1 second | ||||
|             startDataLogging() | ||||
|  | ||||
|             Timber.i("Audio visualizer listening started successfully") | ||||
|         } catch (e: Throwable) { | ||||
|             // If Visualizer cannot be initialized (e.g. permission or device restriction), ensure cleanup | ||||
|             Timber.e(e, "Failed to start audio visualizer listening") | ||||
|             stop() | ||||
|             throw e | ||||
|         } | ||||
| @@ -60,8 +79,45 @@ class VisualizerController( | ||||
|      */ | ||||
|     @Synchronized | ||||
|     fun stop() { | ||||
|         Timber.d("Stopping audio visualizer listening") | ||||
|  | ||||
|         // Stop the logging coroutine | ||||
|         loggingJob?.cancel() | ||||
|         loggingJob = null | ||||
|  | ||||
|         visualizer?.enabled = false | ||||
|         visualizer?.release() | ||||
|         visualizer = null | ||||
|  | ||||
|         // Clear latest data | ||||
|         latestWaveform = null | ||||
|         latestFft = null | ||||
|  | ||||
|         Timber.i("Audio visualizer listening stopped") | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Starts a coroutine that logs raw data samples every 1 second. | ||||
|      */ | ||||
|     private fun startDataLogging() { | ||||
|         loggingJob?.cancel() // Cancel any existing logging job | ||||
|         loggingJob = coroutineScope.launch { | ||||
|             while (isActive) { | ||||
|                 delay(1000) // Wait for 1 second | ||||
|  | ||||
|                 val waveform = latestWaveform | ||||
|                 val fft = latestFft | ||||
|  | ||||
|                 if (waveform != null && fft != null) { | ||||
|                     // Log sample of raw data (first few bytes to avoid too much log spam) | ||||
|                     val waveformSample = waveform.take(8).joinToString(", ") { it.toString() } | ||||
|                     val fftSample = fft.take(8).joinToString(", ") { it.toString() } | ||||
|  | ||||
|                     Timber.d("Raw data sample - Waveform {size: ${waveform.size}, sample: [$waveformSample...]}, FFT {size: {${fft.size}}, sample: [$fftSample...]}") | ||||
|                 } else { | ||||
|                     Timber.d("Raw data sample - No data available yet") | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Adrian Kuta (DZCQIWG)
					Adrian Kuta (DZCQIWG)