raspbianalsacd-rom

How do I feed CD audio tracks into an ALSA-driven sound output device?


I'm using a USB CD/DVD drive without built-in sound decoder and controlling it via ALSA, which already works. The host is a Raspberry Pi 3B with the current Raspbian. Here is the corresponding config file:

pi@autoradio:/etc $ cat asound.conf
pcm.dmixer {
    type dmix
    ipc_key 1024
    ipc_perm 0666
    slave {
        pcm "hw:0,0"
        period_time 0
        period_size 1024
        buffer_size 4096
        rate 192000
        format S32_LE
        channels 2 
    }
    bindings {
        0 0
        1 1
    }
}

pcm.dsnooper {
    type dsnoop
    ipc_key 2048
    ipc_perm 0666 
    slave 
    {
        pcm "hw:0,0"
        period_time 0
        period_size 1024
        buffer_size 4096
        rate 192000
        format S32_LE
        channels 2 
    }
    bindings {
        0 0
        1 1
    }
}

pcm.duplex {
    type asym
    playback.pcm "dmixer"
    capture.pcm "dsnooper"
}

pcm.!default {
    type plug
    slave.pcm "duplex"
}

ctl.!default {
        type hw
        card 0
}

To read the music from CD-DA, I'm gonna use the CDIO++ library. Its cd-info utility recognises both the drive, and the audio CD:

pi@autoradio:/etc $ cd-info
cd-info version 2.1.0 armv7l-unknown-linux-gnueabihf

CD location   : /dev/cdrom
CD driver name: GNU/Linux
   access mode: IOCTL

Vendor                      : MATSHITA
Model                       : CD-RW  CW-8124  
Revision                    : DA0D
Hardware                                  : CD-ROM or DVD
Can eject                                 : Yes
Can close tray                            : Yes
Can disable manual eject                  : Yes
Can select juke-box disc                  : No

Can set drive speed                       : No
Can read multiple sessions (e.g. PhotoCD) : Yes
Can hard reset device                     : Yes

Reading....
  Can read Mode 2 Form 1                  : Yes
  Can read Mode 2 Form 2                  : Yes
  Can read (S)VCD (i.e. Mode 2 Form 1/2)  : Yes
  Can read C2 Errors                      : Yes
  Can read IRSC                           : Yes
  Can read Media Channel Number (or UPC)  : Yes
  Can play audio                          : Yes
  Can read CD-DA                          : Yes
  Can read CD-R                           : Yes
  Can read CD-RW                          : Yes
  Can read DVD-ROM                        : Yes

Writing....
  Can write CD-RW                         : Yes
  Can write DVD-R                         : No
  Can write DVD-RAM                       : No
  Can write DVD-RW                        : No
  Can write DVD+RW                        : No
__________________________________

Disc mode is listed as: CD-DA

I've already got some code to send the PCM data to the sound card and some insight regarding the (rather poorly documented) CDIO API (I know that the readSectors() method is used for reading sound data from the CD sector after sector), but not really a clue on how to hand over the data from the CD-DA input to the ALSA output routine correctly.

Please nopte that mplayer is off-limits to me as this routine will be a part of a larger solution.

Any help would be greatly appreciated.

UPDATE: Does the different block size of an audio CD (2,352 bytes) and of the sound output (910 bytes, at least in my particular case) matter?


Solution

  • CD audio data is just two channels of little-endian 16-bit samples at 44.1 kHz.

    If you output the data to the standard output, you can pipe it into your sound-playing program, or aplay:

    ./my-read-cdda | ./play 44100 2 99999
    ./my-read-cdda | aplay --file-type raw --format cd
    

    If you want to do everything in a single program, replace the read(0, ...) with readSectors(). (The buffer size does not need to have any relation with ALSA's period size or buffer size.)