Interfacciarsi con microfono [C++]

di il
5 risposte

Interfacciarsi con microfono [C++]

Ciao a tutti, questo (se si esclude la presentazione) è il mio primo post, ho fatto la ricerca nei post esistenti ma non ho trovato niente, spero almeno di aver azzeccato la sezione.

Premetto che lavoro su Linux (Fedora 14).
Allora, io dovrei scrivere un programma che, prendendo l'input da microfono, analizzi il segnale e lo sfasi di pigreco per poi ributtarlo fuori.
Il mio problema è prendere l'input da microfono
Ho provato a cercare librerie che mi permettessero di fare ciò e ho trovato PulseAudio, il problema è che è scritta in C (e non in C++), ovvero con printf etc. etc.
Sapendo che Linux tratta le periferiche come file (almeno, così sapevo...), ho provato a cercare un modo di agire a livello più basso, passando per i driver, ma mi è sembrato di impegolarmi per vie decisamente più complicate...

Qualcuno conosce qualcosa che può fare al caso mio? Deve essere in C++ perchè lavoro con altri e ho bisogno di utilizzare anche templates e similari, per il resto vanno bene sia librerie che "tips" per lavorare sui driver.

Grazie mille in anticipo!

5 Risposte

  • Re: Interfacciarsi con microfono [C++]

    In *nix il device audio viene gestito facilmente come un semplice file aprendo /dev/dsp (digital signal processor) e tramite la funzione ioctl si configura.
    Questo è il codice che trovi in rete come esempio:
    
    /*
     * parrot.c
     * Program to illustrate /dev/dsp device
     * Records several seconds of sound, then echoes it back.
     * Runs until Control-C is pressed.
     */
    
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/ioctl.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <linux/soundcard.h>
    
    #define LENGTH 3    /* how many seconds of speech to store */
    #define RATE 8000   /* the sampling rate */
    #define SIZE 8      /* sample size: 8 or 16 bits */
    #define CHANNELS 1  /* 1 = mono 2 = stereo */
    
    /* this buffer holds the digitized audio */
    unsigned char buf[LENGTH*RATE*SIZE*CHANNELS/8];
    
    int main()
    {
      int fd;	/* sound device file descriptor */
      int arg;	/* argument for ioctl calls */
      int status;   /* return status of system calls */
    
      /* open sound device */
      fd = open("/dev/dsp", O_RDWR);
      if (fd < 0) {
        perror("open of /dev/dsp failed");
        exit(1);
      }
    
      /* set sampling parameters */
      arg = SIZE;	   /* sample size */
      status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg);
      if (status == -1)
        perror("SOUND_PCM_WRITE_BITS ioctl failed");
      if (arg != SIZE)
        perror("unable to set sample size");
    
      arg = CHANNELS;  /* mono or stereo */
      status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg);
      if (status == -1)
        perror("SOUND_PCM_WRITE_CHANNELS ioctl failed");
      if (arg != CHANNELS)
        perror("unable to set number of channels");
    
      arg = RATE;	   /* sampling rate */
      status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg);
      if (status == -1)
        perror("SOUND_PCM_WRITE_WRITE ioctl failed");
    
      while (1) { /* loop until Control-C */
        printf("Say something:\n");
        status = read(fd, buf, sizeof(buf)); /* record some sound */
        if (status != sizeof(buf))
          perror("read wrong number of bytes");
        printf("You said:\n");
        status = write(fd, buf, sizeof(buf)); /* play it back */
        if (status != sizeof(buf))
          perror("wrote wrong number of bytes");
        /* wait for playback to complete before recording again */
        status = ioctl(fd, SOUND_PCM_SYNC, 0); 
      if (status == -1)
        perror("SOUND_PCM_SYNC ioctl failed");
      }
    }
    
    http://www.oreilly.de/catalog/multilinux/excerpt/ch14-05.htm

    Come vedi è molto semplice gestirlo.
    Le ALSA (Advanced Linux Sound Architecture), attualmente presenti sulla maggior parte dei sistemi Linux, sono in grado di gestire schede audio con particolari caratteristiche e con funzioni di controllo avanzate. Le API sono scritte in C ma esistono binding per quasi tutti i linguaggi... basta cercare
  • Re: Interfacciarsi con microfono [C++]

    Grazie mille ixamit!
    Ne approfitto per porre un'altra domanda... e se in /dev non ci fosse la cartella dsp? Ho una cartella "dri" (driver?) e "snd" che presumo stia per sound, più altre, ma dsp non c'è...

    Quindi, ricapitolando per vedere se ho capito, o leggo direttamente dal file che mi hai indicato usando la funzione ioctl (che potrebbe essere un'ottima soluzione se trovo il file), oppure mi appoggio alle ALSA, che hanno maggiori potenzialità ma devo controllare che siano installate/installarle e devo cercare i binding per farle andare in C++. Giusto?

    Scusa per le domande, ma sono solo uno studente che cerca di fare qualcosa con quello che impara in università
  • Re: Interfacciarsi con microfono [C++]

    e se in /dev non ci fosse la cartella dsp? Ho una cartella "dri" (driver?) e "snd" che presumo stia per sound, più altre, ma dsp non c'è.
    se c'è snd hai le ALSA installate. puoi verificare con 'aplay -l'
    Strano che tu non abbia la dsp...forse manca *oss*
    Prova a googlare (fedora 14 dsp) per vedere il motivo del perchè non sono state include.
    Quindi, ricapitolando per vedere se ho capito, o leggo direttamente dal file che mi hai indicato usando la funzione ioctl (che potrebbe essere un'ottima soluzione se trovo il file), oppure mi appoggio alle ALSA, che hanno maggiori potenzialità ma devo controllare che siano installate/installarle e devo cercare i binding per farle andare in C++. Giusto?
    Si, tranne il fatto che leggi con la read e scrivi con la write; ioctl serve solo ad impostare il parametri (sample size, stereo ...)
  • Re: Interfacciarsi con microfono [C++]

    Secondo me devi caricarti 'alsa-oss'
  • Re: Interfacciarsi con microfono [C++]

    Grazie ixamit!
    Finalmente ho il mio file dsp (a dire il vero anche dsp1!). Il problema non stava nelle alsa-oss, che avevo già installato, quanto nel file /etc/modprobe.d/dist-oss.conf, dove l'ultima riga era commentata (per disabilitare dsp ed evitare conflitti con pulse audio). Togliendo il commento e riavviando, è apparso magicamente

    Senza il tuo aiuto probabilmente non avrei mai trovato il modo, ho scoperto un sacco di cose solo impostando la macchina prima di cominciare a programmare, chissà quando sbatterò la testa su Fourier e similari cosa verrà fuori
Devi accedere o registrarti per scrivere nel forum
5 risposte