Ejemplo n.º 1
0
        /// <summary>
        /// ユーザを追加する。
        /// </summary>
        /// <param name="id">追加する端末ID</param>
        /// <param name="diffTime">端末間の時間差(相手の時計が進んでいる場合は正の値, 遅れていれば不の値のTicks)</param>
        public void AddUser(string id, long diffTime)
        {
            try
            {
                if (userDictionary.ContainsKey(id))
                {
                    userDictionary[id] = 0;
                }
                else
                {
                    userDictionary.Add(id, 0);
                }

                if (diffTimeDictonary.ContainsKey(id))
                {
                    diffTimeDictonary[id] = diffTime;
                }
                else
                {
                    diffTimeDictonary.Add(id, diffTime);
                }
            }
            catch (Exception e)
            {
                SoundControl.WriteErrorLog(e.ToString());
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// 音声リングバッファからのデータを取り出す。
        /// </summary>
        /// <param name="index">開始位置(BufferPacketSize単位)</param>
        /// <param name="length">取り出すデータの長さ(BufferPacketSize単位)</param>
        /// <returns>音声データ配列</returns>
        private short[] GetData(int index, int length)
        {
            try
            {
                short[] buffer = new short[length * BufferPacketSize];

                // バッファからコピー
                if ((index + length) > RingBufferLength)
                {
                    // リングバッファの境界をまたぐ場合
                    int formerLength = RingBufferLength - index;
                    int latterLength = length - formerLength;
                    Array.Copy(soundBuffer, index * BufferPacketSize,
                               buffer, 0, formerLength * BufferPacketSize);
                    Array.Copy(soundBuffer, 0,
                               buffer, formerLength * BufferPacketSize, latterLength * BufferPacketSize);
                }
                else
                {
                    // 境界をまたぐ処理が必要ない場合
                    Array.Copy(soundBuffer, index * BufferPacketSize,
                               buffer, 0, length * BufferPacketSize);
                }

                return(buffer);
            }
            catch (Exception e)
            {
                SoundControl.WriteErrorLog(e.ToString());
                return(new short[0]);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// バイト列からインスタンスを再構成する。
        /// </summary>
        /// <param name="dataBytes">音声データのバイト列</param>
        /// <returns>再構成したインスタンス</returns>
        public static SoundData CreateInstance(byte[] dataBytes)
        {
            try
            {
                // 時刻の読み取り
                long time  = BitConverter.ToInt64(dataBytes, 0);
                int  index = sizeof(long);

                // 端末IDの読み取り
                int idLength = BitConverter.ToInt32(dataBytes, index);
                index += sizeof(int);
                string id = Encoding.UTF8.GetString(dataBytes, index, idLength);
                index += idLength;

                // 音声データの読み取り
                int      dataLength = (dataBytes.Length - index) / sizeof(double);
                double[] data       = new double[dataLength];
                for (int i = 0; i < dataLength; i++)
                {
                    data[i] = BitConverter.ToDouble(dataBytes, index);
                    index  += sizeof(double);
                }

                return(new SoundData(time, data, id));
            }
            catch (Exception e)
            {
                SoundControl.WriteErrorLog(e.ToString());
                return(null);
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// 音声処理管理部を作成する。
        /// </summary>
        /// <param name="id">この端末のID(どの端末が近くにいるのかの表示に利用)</param>
        /// <param name="sendBack">比較用データ取得deligate</param>
        /// <param name="sendInterval">近接センシング用データ送信周期(ミリ秒, 7000ms以下とする)</param>
        /// <param name="fftLength">比較をかけるサウンドデータのバイト数(32000/s)</param>
        /// <param name="proximityKeepCycle">一度のTrue判定が影響を及ぼす周期数</param>
        /// <param name="soundDirectory">音声ログ(16kbps, 16bit)保存のためのディレクトリ</param>
        /// <param name="errorFile">エラーログを書き出すファイル</param>
        public SoundControl(string id, SendBackSignalDelegate sendBack, int fftLength, int sendInterval, int proximityKeepCycle, string soundDirectory, string errorFile)
        {
            try
            {
                this.id           = id;
                SystemDirectory   = Path.Combine(soundDirectory, "system");
                LogFile           = Path.Combine(SystemDirectory, DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".log");
                diffTimeDictonary = new Dictionary <string, long>();

                sendBackDeligate            = sendBack;
                completeSendBack            = new AsyncCallback(CompleteSendBackMethod);
                SoundControl.soundDirectory = soundDirectory;
                SoundControl.errorFile      = errorFile;

                if (sendInterval > 7000)
                {
                    sendInterval = 7000;
                }
                CreateDirectory();
                this.sendInterval       = sendInterval;
                this.proximityKeepCycle = proximityKeepCycle;
                dataBuffer = new DataBuffer(this, fftLength);


                //音量の設定
                int mixer;
                Mixer.init(out mixer);                //Mixer初期化
                Mixer.SetMainVolume(mixer, 50);       //Mainのボリュームを50%に設定
                Mixer.SetWaveOutVolume(mixer, 50);    //WavOutを50%に設定
                Mixer.SetMicRecordVolume(mixer, 100); //マイク録音を100%に設定

                // デバイス初期化
                CaptureDevicesCollection devices = new CaptureDevicesCollection();
                applicationDevice = new Capture(devices[0].DriverGuid);
                if (applicationDevice != null)
                {
                    inputFormat = new WaveFormat();
                    inputFormat.BitsPerSample         = BitsPerSample;
                    inputFormat.Channels              = Channels;
                    inputFormat.SamplesPerSecond      = SamplesPerSec;
                    inputFormat.FormatTag             = WaveFormatTag.Pcm;
                    inputFormat.BlockAlign            = BlockAlign;
                    inputFormat.AverageBytesPerSecond = AvgBytesPerSec;

                    recordingThread = new Thread(new ThreadStart(RecordWorker));
                    recordingThread.IsBackground = true;
                    CreateCaptureBuffer();
                    isActive = true;
                }
            }
            catch (Exception e)
            {
                SoundControl.WriteErrorLog(e.ToString());
            }
        }
Ejemplo n.º 5
0
 /// <summary>
 /// ログウィンドウに出力する。
 /// </summary>
 /// <param name="log">出力するログ</param>
 public void WriteLogWindow(string log)
 {
     try
     {
         //client.Form.LogWindow.AddLine(log);
     }
     catch (Exception e)
     {
         SoundControl.WriteErrorLog(e.ToString());
     }
 }
Ejemplo n.º 6
0
 /// <summary>
 /// 近接センサ用音声データを送信する。
 /// </summary>
 /// <param name="soundData">送信する音声データ</param>
 public void SendAll(SoundData soundData)
 {
     try
     {
         sendBackDeligate.BeginInvoke((ConversationFieldDetector.ISendable)soundData, completeSendBack, null);
     }
     catch (Exception e)
     {
         System.Windows.Forms.MessageBox.Show(e.ToString());
         SoundControl.WriteErrorLog(e.ToString());
     }
 }
Ejemplo n.º 7
0
 /// <summary>
 /// ユーザを削除する。
 /// </summary>
 /// <param name="id">削除する端末ID</param>
 public void RemoveUser(string id)
 {
     try
     {
         userDictionary.Remove(id);
         nearUserList.Remove(id);
     }
     catch (Exception e)
     {
         SoundControl.WriteErrorLog(e.ToString());
     }
 }
Ejemplo n.º 8
0
 /// <summary>
 /// 常時録音を開始する。
 /// </summary>
 public void Start()
 {
     try
     {
         recordingThread.Start();
         applicationBuffer.Start(true);
     }
     catch (Exception e)
     {
         SoundControl.WriteErrorLog(e.ToString());
     }
 }
Ejemplo n.º 9
0
 /// <summary>
 /// 近接センサ用音声データを送信する。
 /// </summary>
 /// <param name="soundData">送信する音声データ</param>
 public void SendAll(SoundData soundData)
 {
     try
     {
         soundData.Time -= diffTimeDictonary[soundData.ID];
         sendBackDeligate.BeginInvoke((ConversationFieldDetector.ISendable)soundData, completeSendBack, null);
     }
     catch (Exception e)
     {
         SoundControl.WriteErrorLog(e.ToString());
     }
 }
Ejemplo n.º 10
0
 /// <summary>
 /// 音声データをファイルに出力する。
 /// </summary>
 /// <param name="position">出力するリングバッファの位置</param>
 private void Record(int position)
 {
     try
     {
         int     index  = SeekPosition(position, -SpeechCandidateLength);
         short[] buffer = GetData(index, 1);
         encoder.encode(buffer, BufferPacketSize);
     }
     catch (Exception e)
     {
         SoundControl.WriteErrorLog(e.ToString());
     }
 }
Ejemplo n.º 11
0
        /// <summary>
        /// 受信した近接センサ用音声データを処理する。
        /// </summary>
        /// <param name="soundData">受信した音声データ</param>
        public void Receive(SoundData soundData)
        {
            try
            {
                if (!diffTimeDictonary.ContainsKey(soundData.ID))
                {
                    return;
                }

                soundData.Time -= diffTimeDictonary[soundData.ID];
                // コサイン類似度の計算
                double similarity = dataBuffer.Compair(soundData);

                if (similarity > ProximityThreshold)
                {
                    // 類似度が閾値以上なら近接ユーザリストに追加
                    userDictionary[soundData.ID] = proximityKeepCycle;
                    if (!nearUserList.Contains(soundData.ID))
                    {
                        nearUserList.Add(soundData.ID);
                    }
                }
                else
                {
                    int temp;
                    if (userDictionary.TryGetValue(soundData.ID, out temp))
                    {
                        if (temp > 0)
                        {
                            // 一定周期は近接判定を継続
                            userDictionary[soundData.ID] = temp - 1;
                            if (userDictionary[soundData.ID] == 0)
                            {
                                nearUserList.Remove(soundData.ID);
                            }
                        }
                    }
                }

                WriteLog(soundData.ID + " : " + similarity.ToString());
                WriteLogWindow(
                    "\r\n##Proximity##\r\n" + similarity.ToString() + " with " + soundData.ID);
            }
            catch (Exception e)
            {
                System.Windows.Forms.MessageBox.Show(e.ToString());
                SoundControl.WriteErrorLog(e.ToString());
            }
        }
Ejemplo n.º 12
0
        /// <summary>
        /// 常時録音処理を行う。
        /// </summary>
        private void RecordWorker()
        {
            short[] buffer = new short[DataBuffer.PacketSize / sizeof(short)];
            while (isActive)
            {
                try
                {
                    // キャプチャバッファが埋まるまで待機
                    notificationEvent.WaitOne(Timeout.Infinite, true);

                    // キャプチャサイズを算出
                    int capturePosition, readPosition;
                    applicationBuffer.GetCurrentPosition(out capturePosition, out readPosition);
                    int lockSize = readPosition - nextCaptureOffset;
                    if (lockSize < 0)
                    {
                        lockSize += captureBufferSize;
                    }
                    lockSize -= lockSize % notifySize;
                    if (lockSize == 0)
                    {
                        continue;
                    }

                    // キャプチャデータ取得
                    byte[] captureData = (byte[])applicationBuffer.Read(
                        nextCaptureOffset, typeof(byte), LockFlag.None, lockSize);

                    // パケットに切り分けて処理
                    for (int i = 0; i < captureData.Length / DataBuffer.PacketSize; i++)
                    {
                        System.Buffer.BlockCopy(captureData,
                                                DataBuffer.PacketSize * i, buffer, 0, DataBuffer.PacketSize);
                        dataBuffer.AddData(buffer, DetectTalking(buffer), DateTime.Now.Ticks);
                    }

                    // 次回のオフセットを計算
                    nextCaptureOffset += captureData.Length;
                    if (nextCaptureOffset >= captureBufferSize)
                    {
                        nextCaptureOffset -= captureBufferSize;
                    }
                }
                catch (Exception e)
                {
                    SoundControl.WriteErrorLog(e.ToString());
                }
            }
        }
Ejemplo n.º 13
0
 /// <summary>
 /// ログファイルに追記する。
 /// </summary>
 /// <param name="log">追記するログ</param>
 public static void WriteLog(string log)
 {
     try
     {
         using (StreamWriter sw = new StreamWriter(LogFile))
         {
             sw.WriteLine(log);
             sw.Flush();
         }
     }
     catch (Exception e)
     {
         SoundControl.WriteErrorLog(e.ToString());
     }
 }
Ejemplo n.º 14
0
 /// <summary>
 /// プログラム終了処理
 /// </summary>
 public void Close()
 {
     try
     {
         if (isRecording)
         {
             isRecording = false;
             encoder.end();
         }
     }
     catch (Exception e)
     {
         SoundControl.WriteErrorLog(e.ToString());
     }
 }
Ejemplo n.º 15
0
 /// <summary>
 /// 常時録音を終了する。
 /// </summary>
 public void Stop()
 {
     try
     {
         applicationBuffer.Stop();
         if (notificationEvent != null)
         {
             notificationEvent.Set();
         }
     }
     catch (Exception e)
     {
         SoundControl.WriteErrorLog(e.ToString());
     }
 }
Ejemplo n.º 16
0
 /// <summary>
 /// 録音を停止する。
 /// </summary>
 /// <returns>音声ファイル名</returns>
 public string StopRecording()
 {
     try
     {
         if (isRecording)
         {
             isRecording = false;
             encoder.end();
             soundControl.WriteLogWindow("RecStop\r\n");
         }
     }
     catch (Exception e)
     {
         SoundControl.WriteErrorLog(e.ToString());
     }
     return(soundFile + ".mp3");
 }
Ejemplo n.º 17
0
        /// <summary>
        /// 受信した近接センサ用音声データを処理する。
        /// </summary>
        /// <param name="soundData">受信した音声データ</param>
        public void Receive(SoundData soundData)
        {
            try
            {
                // コサイン類似度の計算
                double       similarity = dataBuffer.Compair(soundData);
                StreamWriter writer     = new StreamWriter("000.txt", true);
                writer.WriteLine(similarity.ToString());
                writer.Close();

                if (similarity > ProximityThreshold)
                {
                    // 類似度が閾値以上なら近接ユーザリストに追加
                    userDictionary[soundData.ID] = proximityKeepCycle;
                    if (!nearUserList.Contains(soundData.ID))
                    {
                        nearUserList.Add(soundData.ID);
                    }
                }
                else
                {
                    int temp;
                    if (userDictionary.TryGetValue(soundData.ID, out temp))
                    {
                        if (temp > 0)
                        {
                            // 一定周期は近接判定を継続
                            userDictionary[soundData.ID] = temp - 1;
                            if (userDictionary[soundData.ID] == 0)
                            {
                                nearUserList.Remove(soundData.ID);
                            }
                        }
                    }
                }

                WriteLog(soundData.ID + " : " + similarity.ToString());
                WriteLogWindow(
                    "\r\n##Proximity##\r\n" + similarity.ToString() + " with " + soundData.ID);
            }
            catch (Exception e)
            {
                SoundControl.WriteErrorLog(e.ToString());
            }
        }
Ejemplo n.º 18
0
        /// <summary>
        /// 音声処理部を閉じる。
        /// </summary>
        public void Close()
        {
            if (!isActive)
            {
                return;
            }
            isActive = false;

            try
            {
                Stop();
                dataBuffer.Close();
            }
            catch (Exception e)
            {
                SoundControl.WriteErrorLog(e.ToString());
            }
        }
Ejemplo n.º 19
0
 /// <summary>
 /// 録音を開始する。
 /// </summary>
 /// <param name="position">リングバッファの先頭</param>
 private void StartRecording(int position)
 {
     try
     {
         if (!isRecording)
         {
             isRecording = true;
             soundFile   = Path.Combine(SoundControl.SoundDirectory, GetNowString());
             encoder.setFileName(soundFile);
             encoder.init(SoundControl.SamplesPerSec, 32, 64);
             Record(position);
             soundControl.WriteLogWindow("RecStart\r\n");
         }
     }
     catch (Exception e)
     {
         SoundControl.WriteErrorLog(e.ToString());
     }
 }
Ejemplo n.º 20
0
 /// <summary>
 /// 近接センサ用音声データを送信する。
 /// </summary>
 /// <param name="position">最新バッファ位置</param>
 private void SendFftData(int position)
 {
     try
     {
         int index = GetSendDataPosition(position);
         if (index == -1)
         {
             soundControl.SendAll(
                 new SoundData(timeBuffer[position], new double[0], soundControl.ID));
         }
         else
         {
             double[] fftData = UseFFT.GetPower(GetData(index, fftPacketCount));
             soundControl.SendAll(
                 new SoundData(timeBuffer[index], fftData, soundControl.ID));
         }
     }
     catch (Exception e)
     {
         SoundControl.WriteErrorLog(e.ToString());
     }
 }
Ejemplo n.º 21
0
        /// <summary>
        /// 通信で送るデータに変換
        /// </summary>
        /// <returns>送信バイト列</returns>
        public byte[] GetDataBytes()
        {
            try
            {
                // 時刻と端末IDをバイト列に変換
                byte[] timeBytes     = BitConverter.GetBytes(time);
                byte[] idBytes       = Encoding.UTF8.GetBytes(id);
                byte[] idLengthBytes = BitConverter.GetBytes(idBytes.Length);

                // 全体のバイト列を作成
                int totalLength = timeBytes.Length + idLengthBytes.Length
                                  + idBytes.Length + data.Length * sizeof(double);
                byte[] dataBytes = new byte[totalLength];

                // 時刻と端末IDをコピー
                int index = 0;
                timeBytes.CopyTo(dataBytes, index);
                index += timeBytes.Length;
                idLengthBytes.CopyTo(dataBytes, index);
                index += idLengthBytes.Length;
                idBytes.CopyTo(dataBytes, index);
                index += idBytes.Length;

                // 音声データをコピー
                for (int i = 0; i < data.Length; i++)
                {
                    BitConverter.GetBytes(data[i]).CopyTo(dataBytes, index);
                    index += sizeof(double);
                }

                return(dataBytes);
            }
            catch (Exception e)
            {
                SoundControl.WriteErrorLog(e.ToString());
                return(new byte[0]);
            }
        }
Ejemplo n.º 22
0
        /// <summary>
        /// 近接センサ用音声データを比較する。
        /// </summary>
        /// <param name="soundData">受信した音声データ</param>
        /// <returns>比較結果(類似度)</returns>
        public double Compair(SoundData soundData)
        {
            try
            {
                if (soundData.Data.Length > 1)
                {
                    // データ時刻が最も近いブロックを探す
                    int index = SeekPosition(currentPosition, 100);
                    while (index != currentPosition)
                    {
                        // 簡単に相手のデータ時刻を越えた瞬間とする
                        if (timeBuffer[index] > soundData.Time)
                        {
                            break;
                        }
                        if (++index == RingBufferLength)
                        {
                            index = 0;
                        }
                    }

                    // 対応する自分の音声バッファが有声区間であるか確認
                    bool[] localTalkingFlag = GetTalkFlags(index, fftPacketCount);
                    if (CountBool(localTalkingFlag) > SilentDataThreshold)
                    {
                        // 音声データの比較
                        short[]  data           = GetData(index, fftPacketCount);
                        double[] localFrequency = UseFFT.GetPower(data);
                        return(UseFFT.Compair(localFrequency, soundData.Data));
                    }
                }
            }
            catch (Exception e)
            {
                SoundControl.WriteErrorLog(e.ToString());
            }
            return(0);
        }
Ejemplo n.º 23
0
        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="soundControl">サウンドデータをやりとりするためのSoundControlオブジェクト</param>
        /// <param name="fftLength">比較にかける長さ(32000/秒)</param>
        public DataBuffer(SoundControl soundControl, int fftLength)
        {
            this.soundControl = soundControl;
            encoder           = new Codec.mp3_Encoder();
            isRecording       = false;

            // FFT初期化
            fftInterval    = soundControl.SendInterval / RecInterval * PacketDivisor;
            this.fftLength = 2 ^ ((int)(Math.Log(fftLength) / Math.Log(2)) + 1);
            fftPacketCount = fftLength / BufferPacketSize + 1;
            fftCount       = 0;

            // リングバッファ初期化
            Array.Clear(soundBuffer, 0, soundBuffer.Length);
            Array.Clear(talkFlagBuffer, 0, talkFlagBuffer.Length);
            Array.Clear(timeBuffer, 0, timeBuffer.Length);
            currentPosition = 0;

            // 有声・無声フラグカウント初期化
            silentCount     = SilentCandidateLength;
            silentJudgeHead = RingBufferLength - SilentCandidateLength;
            speechCount     = 0;
            speechJudgeHead = RingBufferLength - SpeechCandidateLength;
        }
Ejemplo n.º 24
0
        /// <summary>
        /// リングバッファにデータを追加する。
        /// </summary>
        /// <param name="sound">音声データ</param>
        /// <param name="talkFlag">有声区間かどうか(無音ならfalse)</param>
        /// <param name="time">音声データの時刻</param>
        public void AddData(short[] sound, bool talkFlag, long time)
        {
            try
            {
                sound.CopyTo(soundBuffer, currentPosition * BufferPacketSize);

                // 分割して処理
                for (int i = 0; i < PacketDivisor; i++)
                {
                    talkFlagBuffer[currentPosition] = talkFlag;
                    timeBuffer[currentPosition]     = time + (RecInterval / PacketDivisor) * i;
                    ProcessData(currentPosition);
                    currentPosition++;
                    if (currentPosition == RingBufferLength)
                    {
                        currentPosition = 0;
                    }
                }
            }
            catch (Exception e)
            {
                SoundControl.WriteErrorLog(e.ToString());
            }
        }
Ejemplo n.º 25
0
        /// <summary>
        /// 有声フラグリングバッファからデータを取り出す。
        /// </summary>
        /// <param name="index">開始位置</param>
        /// <param name="length">取り出す長さ</param>
        /// <returns>有声フラグ配列</returns>
        private bool[] GetTalkFlags(int index, int length)
        {
            try
            {
                bool[] talkFlags = new bool[length];

                // バッファからコピー
                for (int i = 0; i < length; i++)
                {
                    talkFlags[i] = talkFlagBuffer[index++];
                    if (index == RingBufferLength)
                    {
                        index = 0;
                    }
                }

                return(talkFlags);
            }
            catch (Exception e)
            {
                SoundControl.WriteErrorLog(e.ToString());
                return(new bool[0]);
            }
        }