Thanks guys.
Last question: I have to know Objective C and Java to cover both iOs and Android?
I found online code (this is C# I think) that is used to test Microphone inputs.
Can I use this for Android also, or I have to separately write it in Java?
-
public class MicHandle : MonoBehaviour {
2.
3.
private const int FREQUENCY = 48000; // Wavelength, I think.
4.
private const int SAMPLECOUNT = 1024; // Sample Count.
5.
private const float REFVALUE = 0.1f; // RMS value for 0 dB.
6.
private const float THRESHOLD = 0.02f; // Minimum amplitude to extract pitch (recieve anything)
7.
private const float ALPHA = 0.05f; // The alpha for the low pass filter (I don’t really understand this).
8.
9.
public GameObject resultDisplay; // GUIText for displaying results
10.
public GameObject blowDisplay; // GUIText for displaying blow or not blow.
11.
public int recordedLength = 50; // How many previous frames of sound are analyzed.
12.
public int requiedBlowTime = 4; // How long a blow must last to be classified as a blow (and not a sigh for instance).
13.
public int clamp = 160; // Used to clamp dB (I don’t really understand this either).
14.
15.
private float rmsValue; // Volume in RMS
16.
private float dbValue; // Volume in DB
17.
private float pitchValue; // Pitch - Hz (is this frequency?)
18.
private int blowingTime; // How long each blow has lasted
19.
20.
private float lowPassResults; // Low Pass Filter result
21.
private float peakPowerForChannel; //
22.
23.
private float[] samples; // Samples
24.
private float[] spectrum; // Spectrum
25.
private List<float> dbValues; // Used to average recent volume.
26.
private List<float> pitchValues; // Used to average recent pitch.
27.
28.
public void Start () {
29.
samples = new float[SAMPLECOUNT];
30.
spectrum = new float[SAMPLECOUNT];
31.
dbValues = new List<float>();
32.
pitchValues = new List<float>();
33.
34.
StartMicListener();
35.
}
36.
37.
public void Update () {
38.
39.
// If the audio has stopped playing, this will restart the mic play the clip.
40.
if (! audio.isPlaying) {
41.
StartMicListener();
42.
}
43.
44.
// Gets volume and pitch values
45.
AnalyzeSound();
46.
47.
// Runs a series of algorithms to decide whether a blow is occuring.
48.
DeriveBlow();
49.
50.
// Update the meter display.
51.
if (resultDisplay){
52.
resultDisplay.guiText.text = “RMS: " + rmsValue.ToString(“F2”) + " (” + dbValue.ToString(“F1”) + " dB)\n" + “Pitch: " + pitchValue.ToString(“F0”) + " Hz”;
53.
}
54.
}
55.
56.
/// Starts the Mic, and plays the audio back in (near) real-time.
57.
private void StartMicListener() {
58.
audio.clip = Microphone.Start(“Built-in Microphone”, true, 999, FREQUENCY);
59.
// HACK - Forces the function to wait until the microphone has started, before moving onto the play function.
60.
while (!(Microphone.GetPosition(“Built-in Microphone”) > 0)) {
61.
} audio.Play();
62.
}
63.
64.
/// Credits to aldonaletto for the function, http://goo.gl/VGwKt
65.
/// Analyzes the sound, to get volume and pitch values.
66.
private void AnalyzeSound() {
67.
68.
// Get all of our samples from the mic.
69.
audio.GetOutputData(samples, 0);
70.
71.
// Sums squared samples
72.
float sum = 0;
73.
for (int i = 0; i < SAMPLECOUNT; i++){
74.
sum += Mathf.Pow(samples[i], 2);
75.
}
76.
77.
// RMS is the square root of the average value of the samples.
78.
rmsValue = Mathf.Sqrt(sum / SAMPLECOUNT);
79.
dbValue = 20 * Mathf.Log10(rmsValue / REFVALUE);
80.
81.
// Clamp it to {clamp} min
82.
if (dbValue < -clamp) {
83.
dbValue = -clamp;
84.
}
85.
86.
// Gets the sound spectrum.
87.
audio.GetSpectrumData(spectrum, 0, FFTWindow.BlackmanHarris);
88.
float maxV = 0;
89.
int maxN = 0;
90.
91.
// Find the highest sample.
92.
for (int i = 0; i < SAMPLECOUNT; i++){
93.
if (spectrum[i] > maxV spectrum[i] > THRESHOLD){
94.
maxV = spectrum[i];
95.
maxN = i; // maxN is the index of max
96.
}
97.
}
98.
99.
// Pass the index to a float variable
100.
float freqN = maxN;
101.
102.
// Interpolate index using neighbours
103.
if (maxN > 0 maxN < SAMPLECOUNT - 1) {
104.
float dL = spectrum[maxN-1] / spectrum[maxN];
105.
float dR = spectrum[maxN+1] / spectrum[maxN];
106.
freqN += 0.5f * (dR * dR - dL * dL);
107.
}
108.
109.
// Convert index to frequency
110.
pitchValue = freqN * 24000 / SAMPLECOUNT;
111.
}
112.
113.
private void DeriveBlow() {
114.
115.
UpdateRecords(dbValue, dbValues);
116.
UpdateRecords(pitchValue, pitchValues);
117.
118.
// Find the average pitch in our records (used to decipher against whistles, clicks, etc).
119.
float sumPitch = 0;
120.
foreach (float num in pitchValues) {
121.
sumPitch += num;
122.
}
123.
sumPitch /= pitchValues.Count;
124.
125.
// Run our low pass filter.
126.
lowPassResults = LowPassFilter(dbValue);
127.
128.
// Decides whether this instance of the result could be a blow or not.
129.
if (lowPassResults > -30 sumPitch == 0) {
130.
blowingTime += 1;
131.
} else {
132.
blowingTime = 0;
133.
}
134.
135.
// Once enough successful blows have occured over the previous frames (requiredBlowTime), the blow is triggered.
136.
// This example says “blowing”, or “not blowing”, and also blows up a sphere.
137.
if (blowingTime > requiedBlowTime) {
138.
blowDisplay.guiText.text = “Blowing”;
139.
GameObject.FindGameObjectWithTag(“Meter”).transform.localScale *= 1.012f;
140.
} else {
141.
blowDisplay.guiText.text = “Not blowing”;
142.
GameObject.FindGameObjectWithTag(“Meter”).transform.localScale *= 0.999f;
143.
}
144.
}
145.
146.
// Updates a record, by removing the oldest entry and adding the newest value (val).
147.
private void UpdateRecords(float val, List<float> record) {
148.
if (record.Count > recordedLength) {
149.
record.RemoveAt(0);
150.
}
151.
record.Add(val);
152.
}
153.
154.
/// Gives a result (I don’t really understand this yet) based on the peak volume of the record
155.
/// and the previous low pass results.
156.
private float LowPassFilter(float peakVolume) {
157.
return ALPHA * peakVolume + (1.0f - ALPHA) * lowPassResults;
158.
}
159.
}