psykulsk / RpiANC

Active Noise Control on Raspberry Pi
MIT License
116 stars 20 forks source link

raspberry pi xrun issue #1

Closed wesleyck closed 2 years ago

wesleyck commented 4 years ago

Hello, thank you very much for your work. After compiling on the Raspberry Pi, I found that there would be a problem with xrun. At first I thought it was a problem with the capture playback or buffer setting, but this problem still occurred after I adjusted it to a small value. Later, I checked the cpu when it was running, and found that the cpu would reach 130% when it was running, which seemed to be overloaded. I wonder if it is a multi-threaded setting. Looking forward for your response, thank you! Here is error and cpu info: image

psykulsk commented 4 years ago

Hey! How many cores does the CPU you are running this on have? The main loop runs 3 threads, one for capturing new samples, second for the processing of the previously captured samples, and third for playback. I had similar issues as you, when I didn't use threads and run these tasks sequentially. But then I run the multi-threaded version on a Rpi with CPU with 4 physical cores. So I think that the threads could be executed parallelly there and thanks to that there where no xruns.

Let me know!

Actually, I think you would have to increase, not decrease the buffer sizes, then there is more time to send the samples to playback, as the main error is the playback underrun.

wesleyck commented 4 years ago

Hey! How many cores does the CPU you are running this on have? The main loop runs 3 threads, one for capturing new samples, second for the processing of the previously captured samples, and third for playback. I had similar issues as you, when I didn't use threads and run these tasks sequentially. But then I run the multi-threaded version on a Rpi with CPU with 4 physical cores. So I think that the threads could be executed parallelly there and thanks to that there where no xruns.

Let me know!

Actually, I think you would have to increase, not decrease the buffer sizes, then there is more time to send the samples to playback, as the main error is the playback underrun.

Thank you very much for your reply. My Raspberry Pi has 4 cores. I increase the buffer size according to your common sense method, but it still has xrun problems. And the cpu is still more than 100%. Could it be a problem with my hardware sound card?

psykulsk commented 4 years ago

Maybe try to comment out the processing from the main and see whether the xrun errors are still there. Then you will know whether it is caused by the time that processing takes or is it something else.

You also have to check what are the actual buffer sizes set in the capture and playback devices. From what I remember, when I was working on this, when I set a too low size of the buffer, there was no runtime error, but the actual buffers sizes where set to the minimum values defined by the drivers. I think I added some runtime checks and prints to the init_capture and init_playback functions, but you could double check it.

wesleyck commented 4 years ago

When I try to set down the buffer size before, it turns out underrun and some overrun before. I will try the actually physical buffer size and comment main. Appreciate your replay, I will let you know if I figure it out.

wesleyck commented 4 years ago

Hi buddy, sorry to trouble you again. Since my sound card device does not support the alsa driver and can only encode S16_LE, I found that your dc_removal and processing_feedforward_anc modules both accept S32_LE data for processing, so I want to know if there is a problem with 16-bit data processing? And I tried to directly change the sample_type and fixed_sample_type in common.h to the corresponding 16 bits, but I found a lot of dependency errors. Does it only support 32-bit sampling? Looking forward to your reply.

psykulsk commented 4 years ago

Hey, So if you change int32_t to int16_t in this line: https://github.com/psykulsk/RpiANC/blob/master/Headers/common.h#L15 and change capture and playback format from SND_PCM_FORMAT_S32_LE to SND_PCM_FORMAT_S16_LE here https://github.com/psykulsk/RpiANC/blob/master/Sources/playback.cpp#L43 and here https://github.com/psykulsk/RpiANC/blob/master/Sources/capture.cpp#L42 does something brake? I just modified it and it compiled, but I do not have a setup currently to do a proper test.

I would start with a program that first only records and see if that works (use the recTestData target that runs this main for example https://github.com/psykulsk/RpiANC/blob/master/Mains/record_test_data.cpp), then do similar with playback. Then you will know that the capture and playback works and you can try testing the signal processing.

wesleyck commented 4 years ago

Hey, So if you change int32_t to int16_t in this line: https://github.com/psykulsk/RpiANC/blob/master/Headers/common.h#L15 and change capture and playback format from SND_PCM_FORMAT_S32_LE to SND_PCM_FORMAT_S16_LE here https://github.com/psykulsk/RpiANC/blob/master/Sources/playback.cpp#L43 and here https://github.com/psykulsk/RpiANC/blob/master/Sources/capture.cpp#L42 does something brake? I just modified it and it compiled, but I do not have a setup currently to do a proper test.

I would start with a program that first only records and see if that works (use the recTestData target that runs this main for example https://github.com/psykulsk/RpiANC/blob/master/Mains/record_test_data.cpp), then do similar with playback. Then you will know that the capture and playback works and you can try testing the signal processing.

Hello, after I tried S16_LE, it can be played correctly when I did not process the data, indicating that the data is ok. But when I run the process, I found that it was normal for the first 2 minutes, and after about 2 minutes, the sound suddenly became loud, and it showed playback short write, write 110 frames playback short write, write 90 frames playback short write, write 80 frames playback short write, write 70 frames playback short write, write 100 frames playback short write, write 170 frames I don't know if this is the result of adaptation or just the pressure of the processing process, which caused the playback to not get the specified frame in time. In addition, I want to know how the inverted sound compares with the original sound in order to see if it is useful, thank you! I will appreciate u if there are sample WAV test files before and after ANC processing and send me a copy (chengkunhou28@gmail.com) if convenience.Thank you very much!!

psykulsk commented 4 years ago

Yes, the instability may happen, I've also seen it for some input signals, especially the more dynamic ones. I'm not sure why the xrun errors appear when that happens, but I did not have time to investigate that. There is a lot of space for development here :)

Important thing that you have to take into account is the filter coefficients that estimate the secondary path. I did this estimation experimentally with some octave scripts and recordings from the microphones. Octave scripts can be found under links below, but these will not work out of the box. The results I used are specific to my microphones, headphones, speakers and environment so you would have to experiment with doing it yourself to get better results. https://github.com/psykulsk/RpiANC/blob/master/Scripts/OctaveCode/rls_offline_sec_path_modelling.m https://github.com/psykulsk/RpiANC/blob/master/Scripts/OctaveCode/lms_offlince_sec_path_modelling.m

This system was able significantly attenuate only a constant frequency noise. Here is a sample recording of noise reduction of a 1 kHz signal: https://drive.google.com/file/d/1zu5tBbxbBDITIFIQgyDUwIxsOS8fnE36. It was recorded with a an in-ear microphone.

wesleyck commented 4 years ago

Hey! I just solve the xun issue by receiving data by udp and saving the data to file. But now here are two problems that bother me, cpu overload for more than 35 seconds and it can't work at frequencies more than 1500Hz. Although my Raspberry Pi has 4 cores and I have enabled multithreading. But every time I run for more than 35 seconds, the cpu will suddenly rise from the normal 40% to 110%, and then my other processes such as receiving data will not work. Have you tried processing single frequency data for more than 1 minute? And I used a different single frequency from 500Hz to 5000Hz, I found that it can not work normally if it exceeds 1500Hz, have you encountered this problem before?The following is a constant 5khz frequency timing 100 seconds , can you give it a try to get the reverse data? https://drive.google.com/file/d/1CFrzzBAWgKLV77f4_8I0eLAj8To0RZcB/view?usp=sharing Looking forward to your reply, thank you!

psykulsk commented 4 years ago

Generally, active noise control doesn't work well above 1-2 kHz because of the unavoidable latency. Commercial headphones use ANC to dampen low frequency noise and the higher frequencies are supressed by passive methods. So I didn't test higher frequencies, but you can simply put the input samples through a low pass filter and see if that works. I did run some 10 minute tests and I didn't see increase in xruns. Maybe try to disable any memory allocations. For example, do not store any additional samples in vectors and don't write them to a file. But I do not know what's the exact problem. Also, try to profile the application. Add some timers in different sections and see what takes most of the cpu time.

psykulsk commented 4 years ago

As for the test data, I currently do not really have time to assemble the setup and run tests, sorry.

wesleyck commented 4 years ago

Hello, I want to know if it only works for a constant frequency noise and if works for broadband? I have a noise with boradband, I don't know if it works. In addition, I have been troubled by the underrun problem of the playback for a long time. I receive data through udp, and then process and play it, but I don’t know if it is a problem with my parameter settings. The underrun problem will occur during the processing_feedforward_anc. Although I have tried various methods, including modifying the buffer size and period size, from a few to tens of thousands. But mainly when I run programs that include processing_feedforward_anc and playback, underrun will appear. I guess if the processing takes too long, but my Raspberry Pi has a 4-core 4b, and multi-threading should be enough for processing.Appreciating your replay.

psykulsk commented 4 years ago

Hi! Yes, on my setup I achieved attenuation only for constant frequency noise. I tried experimenting with some subband processing here https://github.com/psykulsk/RpiANC/blob/master/Mains/feedforward_anc_subband.cpp , but I didn't have a lot time for it and it doesn't really work. But maybe it can be an inspiration for you :)

Although I believe that because there is this minimal buffer size required by the input and output drivers it may be hard to make it work for the broadband, because processing of blocks of samples instead of just samples makes the convergence time quite long.

Have you tried removing the whole processing step and just copy input samples to output? Does the underrun happen then as well? You have to try it, then you will know whether it is caused by the adaptive algorithm or something else.