[PPA 04] Streams de audio, PortAudio y un oscilador simple

PortAudio es una librería de audio I/O, multiplataforma y de código abierto. Permite escribir programas sencillos de audio en C o C++. Su objetivo es promover el intercambio de software de audio entre los desarrolladores en distintas plataformas. Muchas aplicaciones utilizan PortAudio para audio I/O.

El siguiente programa muestra una lista de las interfaces de audio
disponibles en el sistema:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include <portaudio.h>

int main(){
    // Variable para almacenar errores que PA pueda entregar
    PaError err;

    // Inicialización de la librería
    err = Pa_Initialize();
    if(err!= paNoError){
        printf("PortAudio error:%s\n",Pa_GetErrorText(err));
        exit(1);
    }

    // Pide una lista de dispositivos a la librería
    PaDeviceIndex ndev = Pa_GetDeviceCount();
    if(ndev<0){
        printf("PortAudio error:%s\n", Pa_GetErrorText(ndev));
        exit(1);      
    }

    // Muestra dispositivos de salida      
    printf("\nAudio output devices:\n");
    int i;
    for(i=0; i<ndev; i++){
        const PaDeviceInfo *info = Pa_GetDeviceInfo((PaDeviceIndex) i);
        if(info->maxOutputChannels > 0){
            printf("(%i) %s\n", i, info->name);
        }
    }  

    // Muestra dispositivos de entrada
    printf("\nAudio input devices:\n");
    for(i=0; i<ndev; i++){
        const PaDeviceInfo *info = Pa_GetDeviceInfo((PaDeviceIndex) i);
        if (info->maxInputChannels > 0){
            printf("(%i) %s\n", i, info->name);
        }
    }  
    printf("\n");

    return 0;
}

Este crea un stream de audio, inicializa PortAudio para
que envíe el stream a una interface de salida y envía el stream para que
suene. Se crea una señal diente de sierra.

Las líneas comentariadas cambian la señal de diente de sierra por una senoidal.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <portaudio.h>
#include <math.h>

// Variables que especifican la configuración de la t de sonido
int audioOutDev = 1;
int sampleRate = 44100;
int bufferLength = 64;

// El stream
PaStream *stream;

// Variables que definen la señal que se va a generar
float aquiVamos = 0.0;
int aquiVamosFase = 0;
float frecuencia = 220.0;
float PI = 3.14159265358979323846;

//=======================//
//  Port Audio Callback  //
//=======================//
static int audioCallback( const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData ){
    float *out = (float*)outputBuffer;      

    unsigned int i;
    for(i=0; i<bufferLength; i++){
        aquiVamos += 0.02;
        if(aquiVamos >= 1.0) aquiVamos = -1.0;

        *out = aquiVamos;
        /* printf("%p: %f\n", out, *out);*/
        out++;
    }

    /* unsigned int i;*/
    /* for(i=0; i<bufferLength; i++){*/
    /*     *out = sin(2*PI*frecuencia*(aquiVamosFase+i)/sampleRate);*/
    /*     printf("%p: %f\n", out, *out);*/
    /*     out++;*/
    /* }*/

    /* int aquiVamosFaseMax = sampleRate/frecuencia;*/
    /* printf("AquiVamosFaseMax:%i\n", aquiVamosFaseMax);*/

    /* aquiVamosFase += bufferLength;*/
    /* if(aquiVamosFase >= aquiVamosFaseMax) aquiVamosFase -= aquiVamosFaseMax;*/
    /* printf("AquiVamosFase:%i\n", aquiVamosFase);*/

    return 0;
}


//==============//
//  Init Audio  //
//==============//
void initAudioOut(){
    PaError err;

    err = Pa_Initialize();
    if(err!= paNoError){
        printf("PortAudio error: %s", Pa_GetErrorText(err));
        exit(1);
    }

    // Open an audio out stream.
    PaStreamParameters outParameters;
    memset(&outParameters, '\0', sizeof(outParameters)); // Ponga la var outParameters en su estado inicial (todo ceros)
    outParameters.channelCount = 1;
    outParameters.device = audioOutDev;
    outParameters.sampleFormat = paFloat32;

    err = Pa_OpenStream(&stream, NULL, &outParameters, sampleRate, bufferLength, paNoFlag, audioCallback, NULL);
    if(err!= paNoError){
       printf("PortAudio error:%s", Pa_GetErrorText(err));
       exit(1);
    }

    // Start the stream
    err = Pa_StartStream( stream );
    if(err!= paNoError){
       printf("PortAudio error:%s", Pa_GetErrorText(err));
       exit(1);
    }
}

//========//
//  Main  //
//========//
int main(){
    initAudioOut();

    int termine = 0;
    printf("Entre cualquier caracter para terminar\n");
    while(!termine){
        scanf("%d",&termine);
        sleep(1);    
    }

    return 0;
}

2 thoughts on “[PPA 04] Streams de audio, PortAudio y un oscilador simple

  1. Jack prometió agregar un medidor de consumo de CPU a este programa, Eusse prometió cambiar la ecuación de cálculo de los samples para que suene como el latido de un corazón y Pablo prometió calcular diferentes tipos de ondas. Pongan el código aquí o en la lista de correos.
    Salud!

  2. Thank you for the auspicious writeup. It in truth used to be a amusement account it. Glance complex to more added agreeable from you! However, how could we keep in touch?

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

*

Puedes usar las siguientes etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>