1- // Audio recording (capture) stream setup example.
1+ // Audio recording (capture) example.
22//
3- // Demonstrates how to configure an AAudio input stream for recording audio.
4- // The stream is set to Input direction with 16-bit PCM format at 16 kHz,
5- // which is a common configuration for voice capture on Android.
6- //
7- // After opening and starting the stream, its negotiated properties are
8- // printed. A real application would read captured frames from the stream
9- // using a data callback or a read loop.
3+ // Opens an AAudio input stream at 48 kHz mono 16-bit PCM, reads one second
4+ // of audio frames, and prints basic statistics (total frames, peak amplitude).
105//
116// This program must run on an Android device with AAudio support and
127// the RECORD_AUDIO permission granted.
138package main
149
1510import (
1611 "log"
12+ "math"
13+ "unsafe"
1714
1815 "github.com/xaionaro-go/ndk/audio"
1916)
@@ -25,10 +22,9 @@ func main() {
2522 }
2623 defer builder .Close ()
2724
28- // Configure for mono voice capture at 16 kHz.
2925 builder .
3026 SetDirection (audio .Input ).
31- SetSampleRate (16000 ).
27+ SetSampleRate (48000 ).
3228 SetChannelCount (1 ).
3329 SetFormat (audio .PcmI16 ).
3430 SetPerformanceMode (audio .LowLatency ).
@@ -44,26 +40,46 @@ func main() {
4440 }
4541 }()
4642
47- log .Printf ("capture stream opened" )
48- log .Printf (" sample rate: %d Hz" , stream .SampleRate ())
49- log .Printf (" channel count: %d" , stream .ChannelCount ())
50- log .Printf (" frames per burst: %d" , stream .FramesPerBurst ())
51- log .Printf (" state: %s" , stream .State ())
43+ rate := stream .SampleRate ()
44+ log .Printf ("capture stream opened (rate=%d Hz, ch=%d)" , rate , stream .ChannelCount ())
5245
5346 if err := stream .Start (); err != nil {
5447 log .Fatalf ("start stream: %v" , err )
5548 }
56- log .Printf (" state after start: %s" , stream .State ())
5749
58- // A real application would now read captured audio frames from the
59- // stream, for example by using a data callback registered on the
60- // builder before Open(), or by calling a read method in a loop.
50+ // Read approximately 1 second of audio.
51+ totalFrames := rate
52+ buf := make ([]int16 , 1024 )
53+ var captured []int16
54+
55+ for int32 (len (captured )) < totalFrames {
56+ framesToRead := int32 (len (buf ))
57+ if remaining := totalFrames - int32 (len (captured )); remaining < framesToRead {
58+ framesToRead = remaining
59+ }
60+ n , err := stream .Read (unsafe .Pointer (& buf [0 ]), framesToRead , 1_000_000_000 )
61+ if err != nil {
62+ log .Fatalf ("read: %v" , err )
63+ }
64+ captured = append (captured , buf [:n ]... )
65+ }
6166
6267 if err := stream .Stop (); err != nil {
6368 log .Fatalf ("stop stream: %v" , err )
6469 }
65- log .Printf (" state after stop: %s" , stream .State ())
66- log .Printf (" xrun count: %d" , stream .XRunCount ())
6770
71+ // Compute peak amplitude.
72+ var peak int16
73+ for _ , s := range captured {
74+ if s < 0 {
75+ s = - s
76+ }
77+ if s > peak {
78+ peak = s
79+ }
80+ }
81+
82+ log .Printf ("captured %d frames" , len (captured ))
83+ log .Printf ("peak amplitude: %d (%.1f dBFS)" , peak , 20 * math .Log10 (float64 (peak )/ 32767.0 ))
6884 log .Println ("recording example finished" )
6985}
0 commit comments