VelNet-Unity/TestVelGameServer/Assets/DFVoice/Scripts/IO/MicrophoneInputDevice.cs

174 lines
4.2 KiB
C#

/* Copyright (C) 2014 DaikonForge */
namespace DaikonForge.VoIP
{
using UnityEngine;
[AddComponentMenu( "DFVoice/Microphone Input Device" )]
public class MicrophoneInputDevice : AudioInputDeviceBase
{
public static string DefaultMicrophone = null;
/// <summary>
/// Gets the device that is actively being used to record audio
/// </summary>
public string ActiveDevice
{
get
{
return device;
}
}
public int ChunkSize = 640;
public FrequencyMode Mode = FrequencyMode.Wide;
public KeyCode PushToTalk = KeyCode.None;
public float AmplitudeThreshold = 0f;
private AudioClip recordedAudio;
private int prevReadPosition = 0;
private BigArray<float> resampleBuffer;
private string device = null;
private int recordingFrequency;
private float pushToTalkTimer = 0f;
public override void StartRecording()
{
if( !Application.HasUserAuthorization( UserAuthorization.Microphone ) )
{
Debug.LogWarning( "StartRecording(): Webplayer microphone access denied" );
return;
}
device = DefaultMicrophone;
prevReadPosition = 0;
this.recordingFrequency = AudioUtils.GetFrequency( Mode );
int min, max;
Microphone.GetDeviceCaps( device, out min, out max );
if( max == 0 ) max = 48000;
//if( max == 0 ) max = 16000;
int frequency = Mathf.Clamp( this.recordingFrequency, min, max );
resampleBuffer = new BigArray<float>( ChunkSize, 0 );
recordedAudio = Microphone.Start( device, true, 5, frequency );
}
public override void StopRecording()
{
Microphone.End( device );
}
/// <summary>
/// Switch over to a new device
/// </summary>
public void ChangeMicrophoneDevice( string newDevice )
{
StopRecording();
DefaultMicrophone = newDevice;
StartRecording();
}
void Update()
{
if( !Microphone.IsRecording( device ) || recordedAudio == null )
{
return;
}
float[] tempArray = TempArray<float>.Obtain( ChunkSize );
// in case of recompile
if( resampleBuffer == null )
{
resampleBuffer = new BigArray<float>( ChunkSize, 0 );
}
int readPosition = Microphone.GetPosition( device );
if( readPosition >= ( prevReadPosition + ChunkSize ) )
{
while( readPosition >= ( prevReadPosition + ChunkSize ) )
{
if( canTalk() )
{
recordedAudio.GetData( tempArray, prevReadPosition );
if( exceedsVolumeThreshold( tempArray ) )
{
resample( tempArray );
bufferReady( resampleBuffer, this.recordingFrequency );
}
}
prevReadPosition += ChunkSize;
}
}
else if( prevReadPosition > readPosition )
{
var endReadPos = readPosition + recordedAudio.samples;
var diff = endReadPos - prevReadPosition;
while( diff >= ChunkSize )
{
if( canTalk() )
{
recordedAudio.GetData( tempArray, prevReadPosition );
if( exceedsVolumeThreshold( tempArray ) )
{
resample( tempArray );
bufferReady( resampleBuffer, this.recordingFrequency );
}
}
prevReadPosition += ChunkSize;
if( prevReadPosition >= recordedAudio.samples )
{
prevReadPosition -= recordedAudio.samples;
break;
}
endReadPos = readPosition + recordedAudio.samples;
diff = endReadPos - prevReadPosition;
}
}
TempArray<float>.Release( tempArray );
}
bool exceedsVolumeThreshold( float[] data )
{
if( AmplitudeThreshold == 0f )
return true;
var max = Mathf.Max( data );
return max >= AmplitudeThreshold;
}
void resample( float[] tempArray )
{
//resampleBuffer = new BigArray<float>( tempArray.Length, tempArray.Length );
resampleBuffer.Resize( tempArray.Length );
resampleBuffer.CopyFrom( tempArray, 0, 0, tempArray.Length * 4 );
//Debug.Log( "Resampling from: " + recordedAudio.frequency + ", to: " + this.recordingFrequency );
AudioUtils.Resample( resampleBuffer, recordedAudio.frequency, this.recordingFrequency );
}
bool canTalk()
{
if( PushToTalk == KeyCode.None ) return true;
if( Input.GetKey( PushToTalk ) ) pushToTalkTimer = 0.2f;
pushToTalkTimer -= Time.deltaTime;
return pushToTalkTimer > 0f;
}
}
}