Thank you for your donation!


Cloudsmith graciously provides open-source package management and distribution for our project.


Intermittent loud ticks and no-audio using Spotify
#11
Addendum to Tim's reply

With Spotify playing through card2 = my Khadas Tone Board USB DAC

Code:
pi@moode64:~ $ cat /proc/asound/card2/pcm0p/sub0/hw_params
access: RW_INTERLEAVED
format: S16_LE
subformat: STD
channels: 2
rate: 44100 (44100/1)
period_size: 221
buffer_size: 22050

Regards,
Kent

PS - I'm curious to know what setting got @basmeyer's

Code:
rate: 44100 (352800/8)
Reply
#12
Examining the source shows that period and buffer size are initially set by librespot.
https://github.com/librespot-org/libresp...nd/alsa.rs

The defaults
Code:
const PREFERED_PERIOD_SIZE: Frames = 5512; // Period of roughly 125ms
const BUFFERED_PERIODS: Frames = 4;

Possibly period_size is being overridden in this function ??
Code:
fn open_device(dev_name: &str) -> Result<(PCM, Frames), Box<Error>> {
   let pcm = PCM::new(dev_name, Direction::Playback, false)?;
   let mut period_size = PREFERED_PERIOD_SIZE;
   // http://www.linuxjournal.com/article/6735?page=0,1#N0x19ab2890.0x19ba78d8
   // latency = period_size * periods / (rate * bytes_per_frame)
   // For 16 Bit stereo data, one frame has a length of four bytes.
   // 500ms  = buffer_size / (44100 * 4)
   // buffer_size_bytes = 0.5 * 44100 / 4
   // buffer_size_frames = 0.5 * 44100 = 22050
   {
       // Set hardware parameters: 44100 Hz / Stereo / 16 bit
       let hwp = HwParams::any(&pcm)?;

       hwp.set_access(Access::RWInterleaved)?;
       hwp.set_format(Format::s16())?;
       hwp.set_rate(44100, ValueOr::Nearest)?;
       hwp.set_channels(2)?;
       period_size = hwp.set_period_size_near(period_size, ValueOr::Greater)?;
       hwp.set_buffer_size_near(period_size * BUFFERED_PERIODS)?;
       pcm.hw_params(&hwp)?;

       let swp = pcm.sw_params_current()?;
       swp.set_start_threshold(hwp.get_buffer_size()? - hwp.get_period_size()?)?;
       pcm.sw_params(&swp)?;
   }

   Ok((pcm, period_size))
}
Enjoy the Music!
moodeaudio.org | Mastodon Feed | GitHub
Reply
#13
A properly written alsa backend requests the settings that it wants, but takes into account what values are actually returned.

It basically works like this:

Set this parma as close to x as you can. OK, I actually got y as a return value so I'm going to take y into account and not automatically assume x.

A user can override the parmas so that if an app say requests a buffer size of 0.5 sec and I set the buffer size to 1 sec the app will get that as a return value and that's what alsa will actually use regardless of what the app wants.
Reply
#14
(10-10-2020, 04:06 PM)Tim Curtis Wrote: Examining the source shows that period and buffer size are initially set by librespot.
https://github.com/librespot-org/libresp...nd/alsa.rs

The defaults
Code:
const PREFERED_PERIOD_SIZE: Frames = 5512; // Period of roughly 125ms
const BUFFERED_PERIODS: Frames = 4;

Possibly period_size is being overridden in this function ??
Code:
fn open_device(dev_name: &str) -> Result<(PCM, Frames), Box<Error>> {
   let pcm = PCM::new(dev_name, Direction::Playback, false)?;
   let mut period_size = PREFERED_PERIOD_SIZE;
   // http://www.linuxjournal.com/article/6735?page=0,1#N0x19ab2890.0x19ba78d8
   // latency = period_size * periods / (rate * bytes_per_frame)
   // For 16 Bit stereo data, one frame has a length of four bytes.
   // 500ms  = buffer_size / (44100 * 4)
   // buffer_size_bytes = 0.5 * 44100 / 4
   // buffer_size_frames = 0.5 * 44100 = 22050
   {
       // Set hardware parameters: 44100 Hz / Stereo / 16 bit
       let hwp = HwParams::any(&pcm)?;

       hwp.set_access(Access::RWInterleaved)?;
       hwp.set_format(Format::s16())?;
       hwp.set_rate(44100, ValueOr::Nearest)?;
       hwp.set_channels(2)?;
       period_size = hwp.set_period_size_near(period_size, ValueOr::Greater)?;
       hwp.set_buffer_size_near(period_size * BUFFERED_PERIODS)?;
       pcm.hw_params(&hwp)?;

       let swp = pcm.sw_params_current()?;
       swp.set_start_threshold(hwp.get_buffer_size()? - hwp.get_period_size()?)?;
       pcm.sw_params(&swp)?;
   }

   Ok((pcm, period_size))
}


The latest git master works correctly. Previous to I think july 26th not so much.
Reply
#15
(10-10-2020, 02:20 PM)Tim Curtis Wrote: Hi Jason,

Is it the app or is it ALSA that sets the period and buffer sizes?

Here is when MPD is playing. MPD is configured to output to hw:2,0
Code:
pi@rp3:~ $ cat /proc/asound/card2/pcm0p/sub0/hw_params
access: RW_INTERLEAVED
format: S16_LE
subformat: STD
channels: 2
rate: 44100 (44100/1)
period_size: 5513
buffer_size: 22050

I don't have a Spotify Premium account so not able to test librespot but here is when Airplay renderer is playing. The period_size is same as that reported for when librespot is playing. Shairport-sync is configured to output to plughw:2,0
Code:
pi@rp3:~ $ cat /proc/asound/card2/pcm0p/sub0/hw_params
access: MMAP_INTERLEAVED
format: S16_LE
subformat: STD
channels: 2
rate: 44100 (44100/1)
period_size: 256
buffer_size: 262144

-Tim

Looks like the airplay alsa backend suck too.

For my money a 1 sec buffer with 4 periods is a good safe starting point. MPD seems to be well behaved so it might not be a bad idea to route non-mpd outputs though a custom pcm to make them behave.
Reply
#16
I'm not too keen on doing a work around because eventually it gets fixed upstream. I should prolly post an issue on shairport-sync repo.

We can certainly try Git master. I'll post back with results but prolly not till next week.
Enjoy the Music!
moodeaudio.org | Mastodon Feed | GitHub
Reply
#17
(10-10-2020, 09:30 PM)Tim Curtis Wrote: I'm not too keen on doing a work around because eventually it gets fixed upstream. I should prolly post an issue on shairport-sync repo.

We can certainly try Git master. I'll post back with results but prolly not till next week.

Well it's not really a workaround persay. Really you could route all audio though a custom pcm it would make for a more consistent experience across the board. ALSA by default does basically that for that same reason, only it's less configurable. You wouldn't have to loose your sox mpd resampling either. You can still resample with sox in mpd if the sampling rates match (mpd output >> alsa setting) no resampling in done in ALSA. You could have truly global bit depth, sampling rate and buffer settings.
Reply
#18
You could also provide a passthrough option to satisfy the "bitpurists" that address the hardware directly without touching the audio.
Reply
#19
It's an interesting approach. I've thought about doing something like that but I'm not sure if it can be made compatible with some of the new resampling features we will be introducing in our upcoming release.

Our upcoming 7 release includes a modified MPD that performs what we call "Selective resampling". You set a sample rate target and then choose how you want the source sample rate handled. MPD automatically changes the sample rate on-the-fly.

- Upsample if source < target rate
- Upsample only 44.1K source rate
- Upsample only 44.1K and 48K source rates
- Resample (adhere to base freq)
- Upsample if source < target rate (adhere to base freq)

In this case we would not know the actual sample rate ahead of time in order to modify the PCM.conf.
Enjoy the Music!
moodeaudio.org | Mastodon Feed | GitHub
Reply
#20
(10-10-2020, 10:19 PM)Tim Curtis Wrote: It's an interesting approach. I've thought about doing something like that but I'm not sure if it can be made compatible with some of the new resampling features we will be introducing in our upcoming release.

Our upcoming 7 release includes a modified MPD that performs what we call "Selective resampling". You set a sample rate target and then choose how you want the source sample rate handled. MPD automatically changes the sample rate on-the-fly.

- Upsample if source < target rate
- Upsample only 44.1K source rate
- Upsample only 44.1K and 48K source rates
- Resample (adhere to base freq)
- Upsample if source < target rate (adhere to base freq)

In this case we would not know the actual sample rate ahead of time in order to modify the PCM.conf.


My honest opinion is that upsampling is a waste of CPU cycles unless your sound card doesn't support the sample rate like some crappy old cards that only do 48000 so you have to upsample 44100 for example. Upsampling for no reason, in and of itself never increases sound quality, at best it doesn't hurt it, at worse it degrades it. The only reason it's a thing is because "audiofools" ignorantly believe that more MUST be better. It's about as effective as spending 10 grand on speaker wire.

But you got to give the people what they want or they complain so I get why you're doing it.

- Upsample if source < target rate

Just resample everything except mpd to target rate.

- Upsample only 44.1K source rate

Again upsample everything to some target rate.

By "base freq" I assume you mean some integer multiple of the so like 2 x oversampling or 4 x oversampling.
Reply


Forum Jump: