Hi all,
I’m glad the thread finally gains traction. I did some testing with the code provided by Snarla (thanks again for that). I added another output text field for the raw input value from getTunerVolume and set the positive threshold down to 2 to get better result on my testing devices (iPhone 3G and iPod touch 4th gen), see the adjusted code below.
I did a lot of testing in completely different environment with the Corona code below and the program mentioned in my original post based on AVAudioRecorder from the Cocoa library (Objective-C). My observation is as follows and I’m curious if others have similar experience.
-
The code works in very silent environment with no sudden disturbing noise. The raw value is between 0.2 and 0.3 in that case.
-
If there is just some slight background noise (some running computers in office, typing/clicking sounds) the raw value is fluctuating a lot between 0.4 and 0.6 and it either no blow is recognized or many false once (no blowing, just some noise).
-
In a subway with people around (talking or not) and noise from the train itself the value is constantly around 0.5 to 5.8., so no blow can be detected.
-
If the background is really loud (I attended a concert and tested the program) the raw value is constantly around 0.5 to 0.6. The good thing is that it wasn’t fluctuating and thus not detecting wrong blows, but I really cannot understand why even in such a loud environment the value never grew bigger than around 0.6.
So from my experience it seems that the calculated value for getTunerVolume is way to sensitive. I also tested it on my mac book, there the input has much lower values compared to the iPhone, but also a lot of fluctuation from just office background noise (no people talking) and constantly detects wrong blows. Can anyone else confirm this behavior?
The values read from AVAudioRecorder behave much differently. Even in a subway with noisy people the peak value very seldom reaches 0 (which for AVAudioRecorder means highest volume). Only at the concert I got constantly the peak value 0.
@Snarla could you give us some details regarding getTunerVolume and your testing code? Please see my questions below.
-
What is the highest raw value you measure with an iOS testing device? I never saw any value beyond 0.62 no matter how loud the surrounding are or how much I blow into the microphone.
-
From what I read so far regarding sound pressure/level comparision (eg. http://www.animations.physics.unsw.edu.au/jw/dB.htm) the formula to compare 2 sound levels is as follows:
20 \* log10 \* (p2/p1)
In your code you use not log with base 10 but the natural log (base e), but multiply with 0.301. Further you don’t compare 2 sound levels which is actually needed as dB describes the difference between two levels and is not an absoluate value. Can you explain why exactly you convert the volume in your code in that way?
- You wrote that we currently cannot “play sound back at the same time as you are recording”. Does that affect only background music or any kind of short sound effect? For my current project I only have short sound effects, would it be possible to still use sound recording when no sound is played? E.g. is it possible before playing a sound to stop the recorder and start again after playing the sound (or does that affect performance too much)? That is actually a big bummer, and I was not aware of such limitation as it is not written anywhere in the API documentation.
[code]
– Create an object to access audio input features
local r = media.newRecording()
r:startRecording()
r:startTuner()
– Create an object to hold display items
local g = display.newGroup()
– Simple sound detector
– This just changes the color of a text label in response to a detected sound.
– There are two threshold quantities here that could be used to adjust the sensitivity,
– one is the amount of change that detects sound onset, the other is for sound offset.
– You could connect these to a UI element to allow the user to adjust the sensitivity.
local soundDetector = display.newText( “…”, 0, 0, nil, 22 )
soundDetector:setReferencePoint( display.TopLeftReferencePoint)
soundDetector:setTextColor( 255,255,255, 150 )
soundDetector.x = display.contentWidth/2
soundDetector.y = 0.8*display.contentHeight
local lastV = 0
local threshold = {}
threshold.pos = 2 – adjust these
threshold.neg = 1 – to change sensitivity
local rawOutput = display.newText( “…”, 0, 0, nil, 22 )
rawOutput:setReferencePoint( display.TopLeftReferencePoint)
rawOutput:setTextColor( 255,255,255, 150 )
rawOutput.x = display.contentWidth/2
rawOutput.y = 0.6*display.contentHeight
function soundDetector:enterFrame( event )
local v = r:getTunerVolume()
rawOutput.text = string.format(“raw %4.3f”, v)
if v == 0 then
return
end
– Convert RMS power to dB scale
v = 20 * 0.301 * math.log(v)
soundDetector.text = string.format("%4.2f", v - lastV )
if v > lastV + threshold.pos then
– Detected a level increase
soundDetector:setTextColor( 255,255,100, 255 )
lastV = v
else
if v < lastV - threshold.neg then
– Detected a level drop
soundDetector:setTextColor( 255,255,255, 150 )
lastV = v
else
– Adapt the background level
– Simple running average
lastV = 0.5 * v + 0.5 * lastV
end
end
end
Runtime:addEventListener( “enterFrame”, soundDetector );
g:insert(soundDetector)
[/code] [import]uid: 8111 topic_id: 4708 reply_id: 19181[/import]