MPD to ecasound - plays flac but not MP3

JMF11

Member
2013-12-22 6:40 pm
Whaouh... not so many things are straight forward...

I started to enjoy my new speakers controlled by MPD to ecasound. Was happy and listening music, when one album raised a loud white noise.

After some researches, it appears that my setup plays flac, but not mp3. Doieng some tests and trials by bits, It happened that I had to install mpg123 to be able to play mp3 from the command line with ecasound. One step forward Bu still not working from MPD to ecasound....

In mpd.conf, when I direct the output directly to alsa (and my hardware), I can read mp3.

But still, when I pipe from mpd to ecasound => white noise. I may imagine that ecasound can't detect from the pipe that the file is compressed with mp3?

In the team mpd/ecasound, which one is expected to decompress the mp3 flux? and how is it configured?

No... I won't start to dream about basic analog cables between boxes...:p

JMF
 
I may imagine that ecasound can't detect from the pipe that the file is compressed with mp3?
Correct. The "player" application reads the file and sees the header. As a result it "knows" the file format. When it pipes output to another application the audio stream is just that, an audio stream. The header is not passed along, so the application at the other end of the pipe only sees a bunch of 0's and 1's and knows nothing of what they should mean....

This is your audio michi:

MPD resamples audio to fixed format -- > ALSA loopback --> ecasound --> DACs
 

JMF11

Member
2013-12-22 6:40 pm
Hi,

Understood. But how can it happen that my setup reads .flac files (compressed), and not .mp3 files (also compressed, but different algo).

I did not found a parameter to "force" mpd to translate mp3 to pcm, or to indicate which program to use to read mp3...

flac => mpd => pipe => ecasound => alsa, hardware works
mp3 => mpd => pipe => ecasound => alsa, hardware NOT WORKS
mp3 => mpd => alsa, hardware works
mp3 => command line ecasound => alsa, hardware works

So it works by parts, but not all together.

I imagine that with alsa loopback, it could help, but I have the feeling that in this case I pile software layers with a lot of implicit treatments that I don't control nor understand, and so that it makes things more foggy.

I would be happy to have mpd stream to the pipe a correct PCM (if I'm not wrong about my issue).

Best regards,

JMF
 
JMF11, please post you complete mpd config and output of soxi for the flac and the mp3 files. MPD should convert any of the supported formats to PCM. If you specify fixed output format, it should convert/resample as needed.

You are right, the alsa loopback cannot help you with this. It really does not matter if you feed ecasound with raw samples via pipe (stdin) or alsa loopback (alsa capture).

Perhaps the mp3 file is not 44.1kHz and the MPD output format specification in your MPD's audio_output is incorrect and MPD does not change the format. Since ecasound expects specific fixed format, it would result in mess.
 

JMF11

Member
2013-12-22 6:40 pm
phofman, Thank you for the hints. I will post the requested information this evening as I don't have the files at hand now.

I can already say that I don't have a format command (format "44100:32:2") in the mpd.conf file. I tried to include it, (with respective statement -f:s32_le,2,44100 in the ecasound command) but I had a strange behavior: it was playing music, but very slow, as in the sampling rates were not aligned. As I was working on other aspects, I noted the issue and did not investigated further. I reverted to previous flac working config with no format control on both sides.

I understand that the default in mpd is to use the audio format of the input file. maybe it is more a question of sample_rate:bits:channels than encoding.
JMF
JMF
 
I can already say that I don't have a format command (format "44100:32:2") in the mpd.conf file.

I thought it was the case. This is how the chain works:

MPD/any player reads the original file, converts to PCM first.

The PCM has key attributes - sample rate, sample format, channels count. Most players use float32 or int32 for sample format internally but that is not important here.

Now the player wants to output the samples. If the output module is alsa device (can be alsa-loopback, pulse route to PA, alsa hw:XX, whatever defined), the player has to negotiate parameters acceptable by the sound device. It asks the device: "Give me sample rate nearest to 44.100 (if the original file is 44.100, it would ask for 48.000 for 48k file)". If the sound device can play only 48kHz (i.e. configured in asound.conf for that specific device), it will reply 48.000. Thus the player will know "OK, I have 44.100 source, the output accepts 48kHz only, I will have to resample." The same holds for sample format and channels count.

OR you can tell MPD to always output specific sample rate, format, channels count, using the format command in mpd.conf. That will be fixed for any input data, MPD will do the conversion automatically - for each input file differently as needed.

Now let's look at the other side of the output module.

If there is an alsa device, it will receive all the params of the stream by the player when it opens the device. The player calls snd_open_... alsa-lib directive with hw_params structure containing all the key information.

However, if there is a pipe, the process started by MPD on the other side will not receive any information about the format. It will only receive a stream of bytes via stdin and their meaning must be relayed to the process by some side channel - in this case parameters of the ecasound command hardcoded in mpd.conf. Since it is hardcoded, also the output byte stream format must be hardcoded the same way - thus the need to include the output format command in the pipe output configuration.

The same holds for the alsa-loopback. Eventhough it is alsa device which can relay the stream parameters, there must be ecasound started on the capture side BEFORE mpd opens the playback part of the loopback. As a result mpd cannot change the parameters for different track later on, must keep the format fixed and must resample if another input track does not fit the already running/configured ecasound process.

If you want to avoid resampling while using raw streams carrying no parameters (the pipe), you can use alsa output and configure a special alsa device using the file plugin ALSA project - the C library reference: PCM (digital audio) plugins , prepending the file string with character '|' to tell alsa not to open a file, but run a process using popen call. The alsa library will run the specified command and feed the samples to the stdin - just like MPD's pipe output does. However, it will replace the format keys %r, %c, %b, %f in the command string with actual values of the stream, telling ecasound parameters of the current stdin bytestream. For next track MPD re-opens the device with different params and alsa-lib can start ecasound with different params.

Example e.g. http://www.diyaudio.com/forums/1705320-post847.html (the final version pushed to alsa changed the %b from bytes count to bits count).

That is just another option, handling various tracks without resampling.

maybe it is more a question of sample_rate:bits:channels than encoding

Exactly, encoding of the original file plays no role as it is always decoded to PCM first.
 
The same holds for the alsa-loopback. Eventhough it is alsa device which can relay the stream parameters, there must be ecasound started on the capture side BEFORE mpd opens the playback part of the loopback. As a result mpd cannot change the parameters for different track later on, must keep the format fixed and must resample if another input track does not fit the already running/configured ecasound process.

If you want to avoid resampling while using raw streams carrying no parameters (the pipe), you can use alsa output and configure a special alsa device using the file plugin ALSA project - the C library reference: PCM (digital audio) plugins , prepending the file string with character '|' to tell alsa not to open a file, but run a process using popen call. The alsa library will run the specified command and feed the samples to the stdin - just like MPD's pipe output does. However, it will replace the format keys %r, %c, %b, %f in the command string with actual values of the stream, telling ecasound parameters of the current stdin bytestream. For next track MPD re-opens the device with different params and alsa-lib can start ecasound with different params.

Example e.g. http://www.diyaudio.com/forums/1705320-post847.html (the final version pushed to alsa changed the %b from bytes count to bits count).

That is just another option, handling various tracks without resampling.

Exactly, encoding of the original file plays no role as it is always decoded to PCM first.
My experience stands in contrast to what you (phoman) are saying in the first paragraph quoted above - I use MPD into a loopback with MPD resampling to a fixed format. I always open and play from MPD first, before opening the application taking data out of the loopback. It seems that which ever app connects first to the loopback sets the format for the loopback, and these stay fixed until both sending and receiving applications disconnect (are terminated) from the loopback. So when you say (also in p1) that MPD cannot change the format after it is first established, you are most definitely correct.

Phoman, thanks for posting the other info (second paragraph and onwards, above). I wasn't aware that ALSA could pass format info like that. An ecasound shell script could be used in place of your Sox script and the command line rate and bit depth parameters used in the ecasound format statement. This would eliminate what I consider to be a major drawback of ecasound (having to specify the format). Of course the eventual output device must support this format or there will need to be a conversion done at that stage.

Up to this point, because my DACs only handle 44.1k or 48k audio I have resampled everything ONCE in MPD to 16/48. At least 48kHz gives the IIR filters a little more breathing room between 20kHz and the Nyquist frequency! This has been very reliable for me because it is a simple matter to prevent ALSA from changing those parameters (via the MPD config file) and then everything down the line can be told exactly what format to expect. I'm not going out of my way to get bit-perfect playback. It's just not a priority for me at this point. Also, this allows me to resample on my audio SERVER, which has a more powerful CPU than any of my audio CLIENTS (typically R-Pi 2 or 3). I avoid resampling on the clients due to the heavy CPU resource usage it requires.

I will definitely keep that link on my radar and give it a try at some point in the near future. Using a shell script would allow for a test of the sample rate and, if it is too high for the DAC, to invoke Sox re-sampling/re-formatting before passing the audio to ecasound via a pipe.
 
Last edited:

JMF11

Member
2013-12-22 6:40 pm
Hello,

Working now. I made a stupid mistake, but also learned things in the process thanks to you.

I fixed the format in mpd.conf ouput and in ecasound command input.

What was my stupid mistake: I had put in ecasound command the -f:s32_le,2,4410 AFTER the -i:stdin instead of BEFORE. This changes a lot of things.

Without defining the mpd output and ecasound input format, I was relying on default parameters hence the song parameters. What is strange to me is that now it works, but in fact the song that was working and the one that was not seem to both have the same 16,2,44100 parameters

The working one:
Code:
Input File     : 'HeCanOnlyHoldHer.flac'
Channels       : 2
Sample Rate    : 44100
Precision      : 16-bit
Duration       : 00:02:48.59 = 7434672 samples = 12644 CDDA sectors
File Size      : 18.9M
Bit Rate       : 895k
Sample Encoding: 16-bit FLAC
Comments       :
ALBUM=Back To Black
ALBUM ARTIST=Amy Winehouse
ARTIST=Amy Winehouse
TITLE=He Can Only Hold Her
TOTALTRACKS=10
TRACKNUMBER=10

The one that was not working:
Code:
Input File     : 'test.mp3'
Channels       : 2
Sample Rate    : 44100
Precision      : 16-bit
Duration       : 00:03:31.03 = 9306423 samples = 15827.2 CDDA sectors
File Size      : 5.07M
Bit Rate       : 192k
Sample Encoding: MPEG audio (layer I, II or III)
Comments       :
Title=After It All
Artist=Cat Power
Album=The Greatest
Tracknumber=5
Year=2006
Genre=12

To be able to use soxi on mp3 files, I had to install on my armbian: sox and libsox-fmt-mp3 (for information, I tried to play mp3 after installing sox and before installing libsox-fmt-mp3).


At the moment, I will keep the systematic fixed format, for easeness of implementation and "deterministic" key parameters.

I however keep in mind the cleaner method to pass all meta data to ecasound, which can make a lot of sense.

Best regards,

JMF