Hi,
I am trying to downsample audio that comes from using Microphone.Start and OnAudioFilterRead.
It seems to always record in 44100hz stereo but I need 16000hz mono. I am able to merge the stereo channels to mono fairly easily but downsampling is harder. I tried using c# lib’s like alvas but they do not work on unity due to other dependancies. I am likely going to need to write a low pass filter and then interpolate/decimate the audio to get my clean downsampled audio.
I was hoping if there is a easier way to do this in unity. I am attaching my code so far. It was inspired by some existing code I found on the unity forums.
using UnityEngine;
using System.Collections;
using System.IO;
using System.Collections.Generic;
using System;
public class LiveRec : MonoBehaviour {
FileStream file;
int microphoneMaxRecordingTime;
void Start ()
{
StartWriting();
microphoneMaxRecordingTime=1;
audio.clip = Microphone.Start (null, true, microphoneMaxRecordingTime, AudioSettings.outputSampleRate);
audio.loop = true;
while (!(Microphone.GetPosition(null) > 0))
{
Debug.Log ("Microphone.GetPosition(null)");
}
audio.Play();
}
void OnAudioFilterRead(float[] data, int channels)
{
Debug.Log("channels=" + channels.ToString());
Debug.Log("floats=" + data.Length);
ConvertAndWrite(data);
Array.Clear(data, 0, data.Length);
}
void ConvertAndWrite(float[] dataSource)
{
Int16[] intData = new Int16[dataSource.Length];
//converting in 2 steps : float[] to Int16[], //then Int16[] to Byte[]
Byte[] bytesData = new Byte[dataSource.Length];
//bytesData array is twice the size of
//dataSource array because a float converted in Int16 is 2 bytes.
int rescaleFactor = 32767; //to convert float to Int16
for (int i = 0; i<dataSource.Length/2;i++)
{
//intData <em>= (short)(dataSource_*rescaleFactor);_</em>
_ Int16 leftChannel = (short)(dataSource[i*2]rescaleFactor);
Int16 rightChannel = (short)(dataSource[i*2+1]rescaleFactor);_
_ Byte[] byteArr = new Byte[2];_
* short monoChannel = (short)Math.Round(((int)leftChannel + (int)rightChannel) / 2F);*
_ //byteArr = BitConverter.GetBytes(intData*);
byteArr = BitConverter.GetBytes(monoChannel);
byteArr.CopyTo(bytesData,i2);
* }
Debug.Log(“bytes=”+bytesData.Length.ToString());
file.Write(bytesData,0,bytesData.Length);
} *_
* //Create and start writing the file*
* void StartWriting()*
* {*
* string filePath = Application.dataPath + “/zz.raw”;*
* file = new FileStream(filePath,FileMode.Create); //Create or open our file if exists*
* }*
}