public void ApplyVoiceChannelParms(VoiceParmSet parms, bool reconfigure)
 {
     log.DebugFormat(voiceMgr, "VoiceChannel.ApplyVoiceChannelParms: voiceMgr.defaultPlaybackVolume {0}", voiceMgr.defaultPlaybackVolume);
     ApplyDecodecSettings(parms, reconfigure);
     SetPlaybackVolume(voiceMgr.defaultPlaybackVolume);
     ApplyJitterBufferSettings(parms, reconfigure);
 }
            ///<summary>
            ///    Initialize a new microphone instance, creating the
            ///    FMOD sound object, optionally opening a recording
            ///    stream, and creating and starting a timer instance
            ///    to copy the PCM samples.
            ///</summary>
            public void InitMicrophone(VoiceParmSet parmSet, bool reconfigure)
            {
                log.DebugFormat(voiceMgr, "MicrophoneChannel.InitMicrophone called with recording WAV({0}), Speex({1})", recordingWAV, recordingSpeex);
                if (channelCodec != null)
                    return;
                try {
                    log.Debug(voiceMgr, "MicrophoneChannel.InitMicrophone: Creating codec");
                    encoderOutputBuffer = new byte[maxBytesPerEncodedFrame];
                    if (voiceMgr.runningVoiceBot) {
                        ApplyVoiceBotParms(parmSet, reconfigure);
                        SetTimeOfNextPlayback();
                    }
                    else {
                        encoderInputBuffer = new short[maxSamplesPerFrame];
                        channelCodec = new SpeexCodec();
                        int encodecFrameSize = channelCodec.InitEncoder(maxSamplesPerFrame, samplesPerFrame, samplesPerSecond);
                        if (encodecFrameSize != samplesPerFrame)
                            log.ErrorFormat(voiceMgr, "MicrophoneChannel.InitMicrophone: The encoder frame size {0} != samplesPerFrame " + samplesPerFrame);
                        ApplyMicrophoneSettings(parmSet, reconfigure);
                        // create a sound object
                        FMOD.RESULT result;
                        FMOD.MODE mode = FMOD.MODE._2D | FMOD.MODE.OPENUSER | FMOD.MODE.SOFTWARE | FMOD.MODE.LOOP_NORMAL;
                        lock(voiceMgr.usingFmod) {
                            FMOD.CREATESOUNDEXINFO  exinfo = new FMOD.CREATESOUNDEXINFO();
                            exinfo.cbsize = Marshal.SizeOf(exinfo);
                            exinfo.decodebuffersize = 0;
                            exinfo.length = (uint)(micQueueSize * 2);
                            exinfo.numchannels = 1;
                            exinfo.defaultfrequency = samplesPerSecond;
                            exinfo.format = FMOD.SOUND_FORMAT.PCM16;

                            log.Debug(voiceMgr, "MicrophoneChannel.InitMicrophone: Creating sound");
                            result = voiceMgr.fmod.createSound((string)null, mode, ref exinfo, ref channelSound);
                        }
                        try {
                            ERRCHECK(result);
                        }
                        catch (Exception e) {
                            log.ErrorFormat(voiceMgr, "MicrophoneChannel.InitMicrophone: Error creating microphone sound: {0}; stack trace\n {1}",
                                e.Message, e.StackTrace);
                        }
                        SetMicDevice();
                        micSamples = new short[micQueueSize];
                        if (recordingWAV || recordingSpeex) {
                            log.Debug(voiceMgr, "MicrophoneChannel.InitMicrophone: Calling StartRecording");
                            StartRecording(channelSound, voiceMgr.LogFolderPath("RecordMic"), recordingWAV, recordingSpeex);
                        }
                        log.Debug(voiceMgr, "MicrophoneChannel.InitMicrophone: Calling StartFmodMicUpdates");
                        StartFmodMicUpdates(channelSound);
                        log.Debug(voiceMgr, "MicrophoneChannel.InitMicrophone: Calling StartChannel");
                        StartChannel(false);
                    }
                    micHandlingTimer = new System.Timers.Timer();
                    micHandlingTimer.Elapsed += MicHandlingTimerTick;
                    micHandlingTimer.Interval = 10; // ms
                    micHandlingTimer.Enabled = true;
                    if (usingDataFrameAggregation) {
                        dataFrameAggregator = new DataFrameAggregator(voiceMgr, deviceNumber, this);
                        dataFrameAggregator.Start();
                    }
                    sourceReady = true;
                }
                catch (Exception e) {
                    log.Error(voiceMgr, "MicrophoneChannel.InitMicrophone: Exception " + e.Message + ", stack trace\n" + e.StackTrace);
                }
            }
 ///<summary>
 ///    The constructor creates the VoiceChannel object,
 ///    assigning it the external voiceNumber, and finally
 ///    activates the channel.
 ///</summary>
 public VoiceChannel(VoiceManager voiceMgr, long oid, byte voiceNumber, bool positionalSound, bool voicesRecordSpeex, VoiceParmSet parms)
     : base(voiceMgr, false, voicesRecordSpeex, !positionalSound)
 {
     this.oid = oid;
     this.positionalSound = positionalSound;
     this.voiceNumber = voiceNumber;
     this.channelCodec = new SpeexCodec();
     this.decodeBuffer = new short[playbackQueueSize];
     this.encodedBytes = new byte[maxBytesPerEncodedFrame];
     this.queuedSamples = new CircularBuffer(playbackQueueSize);
     this.voiceReadCallback = new FMOD.SOUND_PCMREADCALLBACK(VoiceChannelReadPCM);
     this.title = "voice" + voiceNumber;
     this.lastSpoke = 0;
     ActivateChannel();
     ApplyVoiceChannelParms(parms, false);
 }
 protected void ApplyTransmissionParms(VoiceParmSet parmSet, bool reconfigure)
 {
     foreach (VoiceParm parm in parmSet.GetParmsOfKindOrDefault(VoiceParmKind.Transmission, reconfigure)) {
         log.DebugFormat(voiceMgr, "VoiceManager.ApplyTransmissionParms: setting voice bot parm {0} to {1}", parm.name, parm.value);
         switch ((TransmissionParm)(parm.ctlIndex)) {
         case TransmissionParm.MaxSavedFrames:
             maxSavedFrames = parm.ret.iValue;
             break;
         case TransmissionParm.UsePowerThreshold:
             usePowerThreshold = parm.ret.bValue;
             break;
         case TransmissionParm.FramePowerThreshold:
             framePowerThreshold = parm.ret.fValue;
             break;
         default:
             log.ErrorFormat(voiceMgr, "VoiceManager.ApplyTransmissionParms: Unknown voice parm '{0}', index {1}", parm.name, parm.ctlIndex);
             break;
         }
     }
 }
 protected void ApplyVoiceBotParms(VoiceParmSet parmSet, bool reconfigure)
 {
     foreach (VoiceParm parm in parmSet.GetParmsOfKindOrDefault(VoiceParmKind.VoiceBot, reconfigure)) {
         log.DebugFormat(voiceMgr, "VoiceManager.ApplyVoiceBotParms: setting voice bot parm {0} to {1}", parm.name, parm.value);
         switch ((VoiceBotParm)(parm.ctlIndex)) {
         case VoiceBotParm.MaxWaitTilNextPlayback:
             maxWaitTilNextPlayback = parm.ret.iValue;
             break;
         default:
             log.ErrorFormat(voiceMgr, "VoiceManager.ApplyVoiceBotParms: Unknown voice parm '{0}', index {1}", parm.name, parm.ctlIndex);
             break;
         }
     }
 }
 protected void ApplyPreprocessorSettings(VoiceParmSet parmSet, bool reconfigure)
 {
     List<VoiceParm> parms = parmSet.GetParmsOfKindOrDefault(VoiceParmKind.Preprocessor, reconfigure);
     log.DebugFormat(voiceMgr, "BasicChannel.ApplyPreprocessorSettings: There are {0} settings", parms != null ? parms.Count : 0);
     if (parms != null) {
         foreach (VoiceParm parm in parms) {
             log.DebugFormat(voiceMgr, "BasicChannel.ApplyPreprocessorSettings: setting {0} to {1}", parm.name, parm.value);
             // DENOISE, MICLEVEL, FRAME_POWER_THRESHOLD
             // and SET_VAD require special treatment
             if (parm.ctlIndex == (int)PreprocessCtlCode.SPEEX_PREPROCESS_SET_DENOISE)
                 CheckRetCode(parm, channelCodec.SetOnePreprocessorSetting((PreprocessCtlCode)parm.ctlIndex, (parm.ret.bValue ? 1 : 2)));
             else if (parm.ctlIndex == (int)PreprocessCtlCode.SPEEX_PREPROCESS_SET_AGC_LEVEL)
                 SetMicLevel(parm.ret.iValue);
             else if (parm.ctlIndex == (int)PreprocessCtlCode.SPEEX_PREPROCESS_SET_VAD && usePowerThreshold)
                 // Turn off VAD if we're using the power
                 // threshold instead of preprocess VAD
                 CheckRetCode(parm, channelCodec.SetOnePreprocessorSetting(PreprocessCtlCode.SPEEX_PREPROCESS_SET_VAD, 0));
             else {
                 switch (parm.valueKind) {
                 case ValueKind.Int:
                     CheckRetCode(parm, channelCodec.SetOnePreprocessorSetting((PreprocessCtlCode)parm.ctlIndex, parm.ret.iValue));
                     break;
                 case ValueKind.Float:
                     CheckRetCode(parm, channelCodec.SetOnePreprocessorSetting((PreprocessCtlCode)parm.ctlIndex, parm.ret.fValue));
                     break;
                 case ValueKind.Bool:
                     CheckRetCode(parm, channelCodec.SetOnePreprocessorSetting((PreprocessCtlCode)parm.ctlIndex, parm.ret.bValue));
                     break;
                 default:
                     log.Error(voiceMgr, "BasicChannel.ApplyPreprocessorSettings: Unknown parm.valueKind " + parm.valueKind);
                     break;
                 }
             }
         }
     }
 }
 protected void ApplyJitterBufferSettings(VoiceParmSet parmSet, bool reconfigure)
 {
     List<VoiceParm> parms = parmSet.GetParmsOfKindOrDefault(VoiceParmKind.JitterBuffer, reconfigure);
     if (parms != null) {
         foreach (VoiceParm parm in parms) {
             log.DebugFormat(voiceMgr, "BasicChannel.ApplyJitterBufferSettings: setting {0} to {1}", parm.name, parm.value);
             CheckRetCode(parm, channelCodec.SetOneJitterBufferSetting((JitterBufferCtlCode)parm.ctlIndex, parm.ret.iValue));
         }
     }
 }
 protected void ApplyEncodecSettings(VoiceParmSet parmSet, bool reconfigure)
 {
     List<VoiceParm> parms = parmSet.GetParmsOfKindOrDefault(VoiceParmKind.Encodec, reconfigure);
     log.DebugFormat(voiceMgr, "BasicChannel.ApplyEncodecSettings: There are {0} settings", parms != null ? parms.Count : 0);
     if (parms != null) {
         foreach (VoiceParm parm in parms) {
             log.DebugFormat(voiceMgr, "BasicChannel.ApplyEncodecSettings: setting {0} to {1}", parm.name, parm.value);
             if (parm.valueKind == ValueKind.Float) {
                 if (parm.ctlIndex == 0)
                     voiceMgr.silentFrameCountDeallocationThreshold = (int)(framesPerSecond * parm.ret.fValue);
                 else
                     log.ErrorFormat(voiceMgr, "BasicChannel.ApplyEncodecSettings: unknown float parm, ctlIndex {0}", parm.ctlIndex);
             }
             // All the rest int parms, and none of them require special treatment
             else if (parm.valueKind != ValueKind.Int)
                 log.ErrorFormat(voiceMgr, "BasicChannel.ApplyEncodecSettings: codec parm '{0}' is not int-valued; instead value type is '{1}'!",
                     parm.name, parm.valueKind);
             else {
                 SpeexCtlCode code = (SpeexCtlCode)parm.ctlIndex;
                 if (code == SpeexCtlCode.SPEEX_SET_QUALITY) {
                     int mode = 0;
                     channelCodec.GetOneCodecSetting(true, SpeexCtlCode.SPEEX_GET_MODE, ref mode);
                     log.DebugFormat(voiceMgr, "BasicChannel.ApplyEncodecSettings: Before setting quality to {0}, mode is {1}",
                         parm.ret.iValue, mode);
                 }
                 CheckRetCode(parm, channelCodec.SetOneCodecSetting(true, code, parm.ret.iValue));
                 if (code == SpeexCtlCode.SPEEX_SET_QUALITY) {
                     int mode = 0;
                     channelCodec.GetOneCodecSetting(true, SpeexCtlCode.SPEEX_GET_MODE, ref mode);
                     log.DebugFormat(voiceMgr, "BasicChannel.ApplyEncodecSettings: After setting quality to {0}, mode is {1}",
                         parm.ret.iValue, mode);
                 }
             }
         }
     }
 }
 protected void ApplyDecodecSettings(VoiceParmSet parmSet, bool reconfigure)
 {
     List<VoiceParm> parms = parmSet.GetParmsOfKindOrDefault(VoiceParmKind.Decodec, reconfigure);
     log.DebugFormat(voiceMgr, "BasicChannel.ApplyDecodecSettings: There are {0} settings", parms != null ? parms.Count : 0);
     if (parms != null) {
         foreach (VoiceParm parm in parms) {
             log.DebugFormat(voiceMgr, "BasicChannel.ApplyDecodecSettings: setting {0} to {1}", parm.name, parm.value);
             // They are all int parms, and none of them require special treatment
             if (parm.valueKind != ValueKind.Int)
                 log.ErrorFormat(voiceMgr, "BasicChannel.ApplyDecodecSettings: codec parm '{0}' is not int-valued; instead value type is '{1}'!",
                     parm.name, parm.valueKind);
             else
                 CheckRetCode(parm, channelCodec.SetOneCodecSetting(false, (SpeexCtlCode)parm.ctlIndex, parm.ret.iValue));
         }
     }
 }
 public void ApplyMicrophoneSettings(VoiceParmSet parmSet, bool reconfigure)
 {
     ApplyTransmissionParms(parmSet, reconfigure);
     ApplyEncodecSettings(parmSet, reconfigure);
     ApplyPreprocessorSettings(parmSet, reconfigure);
     ApplyVoiceBotParms(parmSet, reconfigure);
 }