Beeware makes accessible the android.media
classes MediaPlayer
,Media.Recorder
and AudioRecord
from Python script and I already managed to play and record audio on galaxy23 with Beeware. However MediaRecorder does not provide PCM format output which is required for my application that is concerned with audio signal processing. AudioRecord is capable to sample the mic signal in PCM, however when I try to read the PCM data frames (according to AudioRecord docs https://developer.android.com/reference/android/media/AudioRecord
) with read(byte[] ...)
using a numpy array with dtype=np.int8
or dtype=np.byte
or even trying to use read(float[] ...)
with a numpy array with dtype=np.float32
, I always get the same ambiguity error
android.media.AudioRecord.read is ambiguous for arguments (ndarray, int, int): options are int android.media.AudioRecord.read(byte[], int, int), int android.media.AudioRecord.read(short[], int, int)
It seems to me that AudioRecord cannot recognize my numpy array as byte[]
format although np.int8
or np.byte
are both signed byte as byte[]
is in java, or even cannot recognize it as float[]
format with np.float32
.
Can anybody help me find out what is wrong with what I do? any hint will be much appreciated
I would like to be able to correctly use AudioRecord as all third-party audio modules known to me are not accessible with Beeware even for converting (in-phone) MediaRecorder output file to PCM
UPDATE: Following the answer below by mhsmith I tried the suggestion and it WORKS GREAT!! many thanks! I include the relevant piece of code
def record_file(self,widget):
#Create an AudioRecord object.
self.source=MediaRecorder.AudioSource.MIC
self.sampleRate=8000
self.channel=AudioFormat.CHANNEL_IN_MONO
self.encoding=AudioFormat.ENCODING_PCM_16BIT
self.minBufferSize=AudioRecord.getMinBufferSize(self.sampleRate,self.channel,self.encoding)
self.recorder=AudioRecord(self.source,self.sampleRate,self.channel,self.encoding,self.minBufferSize)
self.recorder.startRecording()
# Create a byte array to store the audio data.
self.byteRate=2*self.sampleRate
self.readTimePeriod=self.minBufferSize/self.byteRate
self.readArray=np.zeros(self.minBufferSize,dtype=np.int8)
self.audioData = jarray(jbyte)(self.readArray)
while True:
#Wait for the buffer to fill-in
time.sleep(self.readTimePeriod)
# Read audio data from the buffer.
self.bytesRead = self.recorder.read(self.audioData,0,self.minBufferSize,0)
# Get the audio data in numpy array from the byte array.
for i in range(self.minBufferSize):
self.readArray[i]=self.audioData[i]
Chaquopy doesn't currently use the dtype of an ndarray when deciding which Java overload to use. This would be a useful feature, and I've created this issue to track it.
Meanwhile, you can work around it by converting the ndarray to a Java array manually:
from java import jarray, jbyte
audio = np.array(..., dtype=np.int8)
audio_record.read(jarray(jbyte)(audio), ...)