microsoft / psi

Platform for Situated Intelligence
https://github.com/microsoft/psi/wiki
Other
529 stars 93 forks source link

"Read Failed" when capturing audio on linux (ReSpeaker Core V2) #29

Open CobraCalle opened 4 years ago

CobraCalle commented 4 years ago

Hi,

I´m trying to get audio capture working on a ReSpeaker Core V2 (http://wiki.seeedstudio.com/ReSpeaker_Core_v2.0/) on Linux. But when I start my sample on linux I get an Error "Read failed"... at first I thought "plughw:0,0" would be wrong, but using anything other than that device name results in error that (more or less) clearly reads like "unknown device". So I think the problem is somewhere else..

Perhaps this will help (result from arecord -l): List of CAPTURE Hardware Devices card 0: seeed8micvoicec [seeed-8mic-voicecard], device 0: 100b0000.i2s1-ac108-pcm0 ac108-pcm0-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0

When I use "hw0,0" as device name I get the following error: Unhandled exception. System.ArgumentException: Hardware params set channels failed. at Microsoft.Psi.Audio.LinuxAudioInterop.Open(String name, Mode mode, Int32 rate, Int32 channels, Format format, Access access) at Microsoft.Psi.Audio.AudioCapture.Start(Action`1 notifyCompletionTime) at Microsoft.Psi.Executive.PipelineElement.b__44_0() at Microsoft.Psi.Scheduling.Scheduler.ExecuteAndRelease(SynchronizationLock synchronizationObject, Action action, SchedulerContext context) at Microsoft.Psi.Scheduling.Scheduler.Run(Object workItem) at System.Threading.QueueUserWorkItemCallbackDefaultContext.Execute() at System.Threading.ThreadPoolWorkQueue.Dispatch() at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

Thanks for your help

Carl

AshleyF commented 4 years ago

It looks like perhaps the device doesn't support single-channel. The AudioCapture component takes an optional AudioCaptureConfiguration with a WaveFormat which defaults to 16KHz, 1 channel, 16-bit PCM. You could try passing a config with different settings.

I'm not sure how to query the hardware for this, but one possible way would be to record a clip with arecord and then look at file details with mediainfo which does show the sampling rate, channel count, etc.

CobraCalle commented 4 years ago

I think you are pointing in the right direction... respeaker@E3BC1:~$ arecord -Dhw:0,0 -f S16_LE -r 16000 -c 1 hello.wav Recording WAVE 'hello.wav' : Signed 16 bit Little Endian, Rate 16000 Hz, Mono arecord: set_params:1305: Channels count non available

When I use stereo, it works fine... respeaker@E3BC1:~$ arecord -Dhw:0,0 -f S16_LE -r 16000 -c 2 hello.wav Recording WAVE 'hello.wav' : Signed 16 bit Little Endian, Rate 16000 Hz, Stereo ^CAborted by signal Interrupt...

But using two channels produces another error... but interestingly not an exception. it just prints "Seqmentation faul" to the console and stops... respeaker@E3BC1:/mnt/Test$ ./ConsoleApp3 Please enter the device name plughw:0,0 Please enter the sampling rate 16000 Please enter the channel count 2 Segmentation fault respeaker@E3BC1:/mnt/Test$

Here is the code from my test app (xxx is a SimpleConsumer that does nothing else than printing a message to the console in "Receive"): using (var pipeline = Microsoft.Psi.Pipeline.Create()) { //var devices = AudioCapture.GetAvailableDevices();

            //foreach (var device in devices)
            //{
            //    Console.WriteLine(device);
            //}

            //Console.ReadLine();

            //audioCaptureConfiguration.OptimizeForSpeech = true;
            //audioCaptureConfiguration.OutputFormat = Microsoft.Psi.Audio.WaveFormat.Create16kHz1Channel16BitPcm();

            var audioCaptureConfiguration = new Microsoft.Psi.Audio.AudioCaptureConfiguration();

            Console.WriteLine("Please enter the device name");
            audioCaptureConfiguration.DeviceName = Console.ReadLine();

            Console.WriteLine("Please enter the sampling rate");
            var samplingRate = int.Parse(Console.ReadLine());

            Console.WriteLine("Please enter the channel count");
            var channelCount = int.Parse(Console.ReadLine());

            audioCaptureConfiguration.Format = Microsoft.Psi.Audio.WaveFormat.CreatePcm(samplingRate, 16, channelCount);

            using (var audioCapture = new Microsoft.Psi.Audio.AudioCapture(pipeline, audioCaptureConfiguration))
            {
                var audioInput = (Microsoft.Psi.IProducer<Microsoft.Psi.Audio.AudioBuffer>)audioCapture;

                audioInput.PipeTo(new xxx(pipeline));

                //pipeline.Run();

                using (pipeline.RunAsync())
                {
                    Console.ReadLine();
                }
            }
        }

What does Seqmentation fault mean?

Perhaps this could help... https://stackoverflow.com/questions/48588513/segmentation-fault-in-alsa-capturing-example