예제 #1
0
        private static Dictionary <string, double[]> loadKeywordHistograms()
        {
            var result = new Dictionary <string, double[]>();

            foreach (var keywordFilename in Directory.EnumerateFiles(Directory.GetCurrentDirectory(), "*.wav", SearchOption.TopDirectoryOnly))
            {
                var wavFile = new WavFile(keywordFilename);
                if (wavFile.ReadMono16bit(out short[] samples))
                {
                    string keyword = Path.GetFileNameWithoutExtension(keywordFilename);
                    result[keyword] = calculateFFT(samples);
                }
            }
            return(result);
        }
예제 #2
0
        static async Task Main(string[] args)
        {
            // =============================================================================================================
            // inspired by: https://stackoverflow.com/questions/4087727/openal-how-to-create-simple-microphone-echo-programm

            string captureDeviceSpecifier = Alc.GetString(IntPtr.Zero, Alc.CaptureDeviceSpecifier);

            Console.WriteLine("Capture device name: " + captureDeviceSpecifier);

            //var audioDevice = Alc.OpenDevice(null);

            ////var errorCode = Alc.GetError(audioDevice); // TODO: check this after each Alc call
            ////var errorCode = Al.GetError(); // TODO: check this after each Al call

            //var context = Alc.CreateContext(audioDevice, null);
            //Alc.MakeContextCurrent(context);

            const int frequency     = 44100;
            const int keywordLength = (int)(frequency);

            var captureDevice = Alc.CaptureOpenDevice(captureDeviceSpecifier, frequency, format: Al.FormatMono16, buffersize: frequency);

            string deviceName = Alc.GetString(captureDevice, Alc.DeviceSpecifier);

            Console.WriteLine($"{deviceName} is open for capture.");

            if (args.Length > 0 && args[0] == "record")
            {
                while (true)
                {
                    Console.Write("Enter keyword name: ");
                    string keywordName = Console.ReadLine();
                    if (string.IsNullOrWhiteSpace(keywordName))                     // exit if nothing entered
                    {
                        break;
                    }

                    Alc.CaptureStart(captureDevice);
                    Console.WriteLine("recording keyword...");                     // need new line for intensity visualization

                    short[] samples = captureSamples(captureDevice, frequency, keywordLength);

                    Alc.CaptureStop(captureDevice);

                    int fileIndex = 0;
                    while (File.Exists($"{keywordName}.{fileIndex}.wav"))
                    {
                        fileIndex += 1;
                    }

                    // write sound file
                    {
                        string filename = $"{keywordName}.{fileIndex}.wav";
                        Debug.Assert(samples.Length >= keywordLength);
                        var wavFile = new WavFile(filename)
                        {
                            SamplesPerSecond = frequency, SamplesTotalCount = keywordLength                                                           /* trim samples */
                        };
                        wavFile.WriteMono16bit(samples);
                        Console.WriteLine($"wav file was saved.");
                    }

                    // create spectrogram and save as image
                    {
                        int width = (int)Math.Sqrt(samples.Length * 2);                         // TODO: make better formula for square images
                        var bins  = samples.Partition(size: width);

                        var spectrogram = new List <double[]>();

                        foreach (var bin in bins)
                        {
                            double[] histogram = calculateFFT(bin.ToArray());
                            spectrogram.Add(histogram);
                        }

                        using (Bitmap bitmap = new Bitmap(spectrogram.Count, spectrogram[0].Length))
                        {
                            for (int i = 0; i < spectrogram.Count; i++)
                            {
                                for (int j = 0; j < spectrogram[i].Length; j++)
                                {
                                    double value      = spectrogram[i][j];
                                    double pixelValue = Math.Max(0, Math.Min(255, value * 10));                                     // TODO: do not trim values, make better multiplying factor
                                    byte   color      = (byte)(pixelValue);
                                    bitmap.SetPixel(i, j, Color.FromArgb(color, color, color));
                                }
                            }
                            string filename = $"{keywordName}.{fileIndex}.png";
                            bitmap.Save(filename, ImageFormat.Png);
                            Console.WriteLine($"png file was saved.");
                        }
                    }
                }
            }
            else
            {
                Alc.CaptureStart(captureDevice);
                Console.WriteLine("listening for keyword...");                 // need new line for intensity visualization
                var reporter = new ClapDetector.Client.Reporter();
                while (true)
                {
                    short[] samples = captureSamples(captureDevice, frequency, keywordLength);
                    // TODO: generate spectrogram image and compare to existing models
                    Console.WriteLine("samples taken");

                    string replyMessage = await reporter.ReportClapAsync();

                    System.Console.WriteLine($"[{DateTime.UtcNow:HH:mm:ss.fff}]: {replyMessage}");
                }
                Alc.CaptureStop(captureDevice);
            }

            // clean up
            Alc.CaptureCloseDevice(captureDevice);
            Alc.MakeContextCurrent(IntPtr.Zero);
            //Alc.DestroyContext(context);
            //Alc.CloseDevice(audioDevice);
        }