50 ways... Music are bytes

De wikijoan
Salta a la navegació Salta a la cerca

Objectius

Introducció: PCM

250px-Pcm.png

Primer de tot, convé recordar perquè parlem de PCM, i perquè tenim dispositius pcm

$ ls /dev/snd
by-path    controlC1  hwC0D0  midiC3D0  midiC3D2  pcmC0D0c  pcmC1D3p  timer
controlC0  controlC3  hwC1D0  midiC3D1  midiC3D3  pcmC0D0p  seq

Pulse-code modulation (PCM) is a method used to digitally represent sampled analog signals. It is the standard form of digital audio in computers, Compact Discs, digital telephony and other digital audio applications. In a PCM stream, the amplitude of the analog signal is sampled regularly at uniform intervals, and each sample is quantized to the nearest value within a range of digital steps.

PCM streams have two basic properties that determine their fidelity to the original analog signal: the sampling rate, the number of times per second that samples are taken; and the bit depth, which determines the number of possible digital values that each sample can take.

És a dir, el dispositiu pcm en la nostra targeta de so representa els conversors ADC que samplegen el senyal d'àudio que li arriba a una freqüència de mostreig determinada i amb una resolució de bits.

Desenvolupament

Capturar amb arecord Una Plata d'Enciam (raw)

Per gravar l'àudio no és tan fàcil amb la UA-25EX, perquè vull gravar amb un sol micro i em trobo amb un problema que ja m'hi havia trobat:

$ arecord -v -f S16_LE -r 8000 -c 2 -D plughw:2,0 foobar.raw
$ aplay -D plughw:2,0 foobar.raw

El tema és que jo només vull gravar un sol canal, amb un sol micro, i l'opció -c 1, que de fet és l'opció per defecte, no funciona. Això ja estava discutit a:

La solució és:

$ joe $HOME/.asoundrc

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


pcm.record_left {
   type        dsnoop
   ipc_key 234884
   slave {
       pcm     "hw:2,0"
       channels 2
   }
   bindings.0  0
}
pcm.record_right {
   type        dsnoop
   ipc_key 2241234
   slave {
       pcm     "hw:2,0"
       channels 2
   }
   bindings.0  1
}

(ficar el valor correcte de hw:2,0 o hw:1,0, on estigui la UA25EX)

$ arecord -v -f S16_LE -r 8000 -c 1 -D plug:record_left foobar.raw

Això són dades crues (raw). Amb el Audacity puc mirar la ona fent Importar > dades cures (sample rate 8000)

Per visualitzar les dades hexadecimals del fitxer (els primers 200 bytes):

$ xxd -l 200 -p foobar.raw

52494646b465000057415645666d74201000000001000100401f0000803e
000002001000646174619065000000000000000000000000000000000000
00000000000000000000000000000100ffff0100ffff0100ffff00000100
fdff2d003b00320034002e00390032002f00320030002c00260028002500
22002600150012000e00140022000d000b00080001001800fffff0ff0400
feff1000f3ff01000400f6ff0e00f8ff15000e0012000c00fbff0c00feff
0900e5ff02000200effffffff3fffbffebfff8ff
---

Per calcular el tamany d'aquesta ristra de caràcters hexadecimals:

61 columnes *868 línies = 52948 caràcters hexadecimals. Divideixo per dos i tinc el número de bytes: 26474 bytes

i és precisament això el que ocupa el meu raw audio:

$ ls -la foobar.raw 
-rw-r--r-- 1 joan joan 26044 des 13 23:08 foobar.raw

Són 1,625 segons. El mostreig era de 8000fps i les dades eren en format S16_LE (resolució de 16 bits per mostra). Per tant:

1,625 sec * 8000 mostres/sec * 2 bytes/mostra = 26000 bytes

Playback del raw audio

Per tal de què soni la canço evidentment podem utilitzar aplay

$ aplay -v -f S16_LE -r 8000 -c 1 -D plughw:2,0 -t raw foobar.raw

però potser queda més clar que la informació està en els bytes si fem:

$ cat foobar.raw | aplay -v -f S16_LE -r 8000 -c 1 -D plughw:2,0 -t raw

Recordem que l'experiment típic és produir soroll blanc:

$ cat /dev/urandom | aplay  -r 8000 -D plughw:2,0
$ cat /dev/urandom | aplay  -r 44100 -D plughw:2,0

provant diferents funcions del rate obtinc soroll blanc més o menys greu.

Si vull utiltizar algo com redirigir els meus bytes a /dev/audio o /dev/dsp, ho tinc malament amb ALSA, doncs aquests dispositius apareixien quan OSS era el servidor d'audio dels sistemes linux. Ara, amb ALSA com a servidor d'àudio, aquests dispositius ja no apareixen. La única cosa similar que es pot fer és utiltizar padsp (PulseAudio OSS Wrapper), similar a:

$ cat /dev/urandom | padsp -d tee /dev/audio > /dev/null

però redirigir el meu fixer foobar.raw no obtinc el resultat esperat perquè en algun moment hem de definir el format en què vénen les dades:

$ cat foobar.raw | padsp -d tee /dev/audio > /dev/null

plyback del raw audio amb node.js

script speaker.js:

    I A  speaker.js (Modified)(java)  Row 7    Col 19   9:53  Ctrl-K H for help
var Speaker = require('speaker');

// Create the Speaker instance
var speaker = new Speaker({
  channels: 1,          // 1 channel
  bitDepth: 16,         // 16-bit samples
  sampleRate: 8000     // 8000 Hz sample rate 
});                  
   
// PCM data from stdin gets piped into the speaker
process.stdin.pipe(speaker);

I executem el script:

$ cat foobar.raw | node speaker.js

Enllaços

*Blog: *Video:
creat per Joan Quintana Compte, desembre 2013