11

Getting access to the user's microphone through navigator.getUserMedia is pretty easy. But what if I'm using a mobile browser and want to pick up audio from a distance, like with a "speakerphone" mode?

How would I go about achieving this? There seem to be native apps that can achieve this, but what about Web Audio?

The purpose of this is for sending messages between devices using DTMF. I have already achieved this with my laptop because its microphone can record surrounding audio from a great distance, but any mobile phone I have access to seems to only record audio near the "mouthpiece" and so I have to hold the phone extremely close to the source speaker for even a slight chance of having a message received. This defeats the purpose unless I can get the mobile microphone to pick up audio from a distance.

EDIT: By distance, I mean greater than a few feet, as opposed to mere centimeters. Ambient sounds, as opposed to sound localized next to the microphone.

Ten Bitcomb
  • 2,316
  • 1
  • 25
  • 39
  • Are you sure it's a different "mode" when in speaker-mode or are you just assuming all this? – nicholaswmin May 07 '16 at 22:04
  • @NicholasKyriakides I assumed a different mode exists as doing an amplification of the incoming waveform does not seem to improve the quality enough for me to decode my audio signal. By amplification, I'm just multiplying the samples. I didn't think that would work anyway, but it was worth a try. The Sound Analyzer app for Android, which is doing something very similar to what I am trying to achieve, is able to pick up distant sounds and draw a spectrogram, so either I'm not doing something correctly or it's impossible with Web Audio. – Ten Bitcomb May 07 '16 at 22:13
  • This may help you https://webrtc.github.io/samples/src/content/devices/input-output/ – Blindman67 May 08 '16 at 22:29
  • The ambient microphone of smartphones may be several physical devices but I think they are one device in the OS. So when you want a better audio, you just increase the gain of the microphone and browser lets the OS handle it. I am making assumptions but that is how it should work. So try increasing the gain as in (should work in Chrome, not sure about others): http://www.html5rocks.com/en/tutorials/webaudio/intro/ – Gokhan Kurt May 10 '16 at 06:10
  • @Blindman67 Both of your comments are relevant answers to my question so, if either of you want to elaborate your comments into answers, that'd be cool. In short, there actually is a separate mode for speakerphone; having adapted the mediaDevices sample in the first link, the device literally comes up as "speakerphone". Though I'm now pretty sure that this was already the default in my case anyway. Using the gainNode also adjusts the volume of the microphone, as seen in the html5rocks tutorial. But it turns out that my problem is likely unrelated to the mic input. – Ten Bitcomb May 11 '16 at 16:17
  • @Gökhan Kurt See above ^^. – Ten Bitcomb May 11 '16 at 16:17
  • Please define "from a distance" – Charlie May 12 '16 at 00:00
  • @Charlie See my edit. – Ten Bitcomb May 12 '16 at 00:11
  • Ok @Ravenstine, I'll play around with this tonight a bit. I would imagine it should be a combination of gain and BiQuad filters etc... Also, It seems like there might be a gate on the signal coming to the audio api, because the mic should become more sensitive with more gain, even in the digital world. You may want to start looking there in the mean time and confirm that such a gate (noise gate) exists or there is some default setting for compression expansion. There is no reason you shouldn't be able to process signals from only a few feet away. – Charlie May 12 '16 at 00:40
  • @Charlie Thanks, I didn't consider a noise gate. If it helps at all, this is the source code of my project, which includes a demo: https://github.com/Ravenstine/airhash – Ten Bitcomb May 12 '16 at 01:32
  • ^^ NOTE: The demo works on desktop Chrome, fails with mobile Chrome on Samsung Galaxy S5 and HTC One S. – Ten Bitcomb May 12 '16 at 02:29
  • good phones use multiple microphones to determine what to transmit. Your phone is working as intended by blocking noises coming from further away then your mouth – Paul Collingwood May 12 '16 at 10:51
  • @Paul Collingwood Would that be the case in speakerphone mode? And how come spectrogram apps can pick up minute sounds through speakerphone? – Ten Bitcomb May 12 '16 at 15:25
  • probably not, and different mode, different configuration. – Paul Collingwood May 13 '16 at 07:35
  • Check out if this example is relevant with what you are after http://stackoverflow.com/questions/21574335/navigator-getusermedia-audio-recording-howto-set-volume-input-level-of-micro –  May 14 '16 at 20:07

3 Answers3

3

I am answering my own question here. Thanks to everyone who helped out, though none of the actual answers posted here were satisfactory, IMO.

On newer versions of Chrome, navigator.mediaDevices has a function called enumerateDevices which can be used to list available hardware devices, including microphones. As it turns out, this does return a "speakerphone" device on my Android phone. So, if you have a device where you suspect that speakerphone isn't set as the default browser microphone, and you(or your user) is on Chrome version 47 or above, you can use the device IDs returned by enumerateDevices to specify a specific microphone.

So, if your user chooses an option in a select element for a specific microphone device, you would take the ID for that device and pass it to getUserMedia.

navigator.getUserMedia({ audio: {deviceId: {exact: <insert device uuid here>}} }, callback)

Note that, as of this posting, the enumerateDevices API is only available on Chrome. In any other browser or web view, this probably won't work.

If the volume of the microphone happens to be too low for your application, you can increase it by creating a gainNode for your AudioContext.

volume     = context.createGain()
volume.gain.value = 3 // raises the volume to 300%
audioInput = context.createMediaStreamSource(e)
audioInput.connect(volume)

Or, if you are dealing with raw samples, you can literally multiply each sample by a number before passing them to whatever function you are using to process them.

Ten Bitcomb
  • 2,316
  • 1
  • 25
  • 39
2

This cannot be done as it's directly related to the hardware of the device. If the device hardware (microphone) cannot pick up sounds from meters away, then there's nothing that can be done.

  • 1
    This would be correct if my hardware did not support this, but it does. See the comments above; my original question has been answered, just not typed up into a formal answer. It turned out that, while there is indeed a "speakerphone" mode, it was not the actual problem as that was the default device. Nor does the actual problem appear to be gain node volume. At this point, I believe it's a software issue as my goal is to pick up frequency presence, and I have apps that doe this, but I can't seem to accomplish this on mobile Chrome(but I can on desktop). – Ten Bitcomb May 12 '16 at 19:48
  • 1
    You are, indeed, welcome to revise your answer based on the comments above. There's still a bounty to go to someone, after all. :) – Ten Bitcomb May 12 '16 at 19:50
  • Ok, maybe a web audio documentation can help answer if it's possible to do this on mobile chrome –  May 12 '16 at 20:15
0

Two years ago, I implemented a webrtc (using google example) that works on mobile web browser, and the sound is captured with ambience levels. I really didn't a deep code analysis of google libraries but maybe you can start here.