C/Visual C - de c++ a tarjeta de sonido

 
Vista:

de c++ a tarjeta de sonido

Publicado por Jesús Trujillo (3 intervenciones) el 20/02/2003 09:21:45
alguien sabe como puedo mandar directamente unas muestras de sonido a la tarjeta de sonido mientras estoy procesandolas para escucharlas sin necesidad de escribir otro fichero wav??gracias :)))

Otra duda por si alguien lo sabe, pk cuando tengo una muestra entera de audio suena perfecto y cuando al procesarla se multiplica o se suma por un numero no entero (por ej. 0,5) distorsiona una barbaridad?gracias de nuevo, encantado de aprender de ustedes :)
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de Alejandro

Envío directo de muestras de sonido a la tarjeta de sonido y manejo de distorsión

Publicado por Alejandro (1153 intervenciones) el 06/05/2025 00:26:12

Solución para enviar muestras de sonido directamente



Para enviar muestras de sonido directamente a la tarjeta de sonido en C/C++, puedes utilizar la API de Windows, específicamente la API de audio de Windows (WinMM). A continuación, te muestro un ejemplo básico de cómo hacerlo:

Ejemplo de código en C++



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
#include <windows.h>
#include <mmsystem.h>
#include <iostream>
 
void reproducirSonidoDirectamente(short* muestras, DWORD numMuestras) {
    // Configuración del formato de audio
    WAVEFORMATEX wfx;
    wfx.wFormatTag = WAVE_FORMAT_PCM;
    wfx.nChannels = 1; // Mono
    wfx.nSamplesPerSec = 44100; // Frecuencia de muestreo
    wfx.wBitsPerSample = 16; // Bits por muestra
    wfx.nBlockAlign = (wfx.nChannels * wfx.wBitsPerSample) / 8;
    wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
 
    // Abrir el dispositivo de audio
    HWAVEOUT hWaveOut;
    if (waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL) != MMSYSERR_NOERROR) {
        std::cerr << "Error al abrir el dispositivo de audio." << std::endl;
        return;
    }
 
    // Preparar el buffer de audio
    WAVEHDR waveHdr;
    waveHdr.lpData = (LPSTR)muestras; // Puntero a las muestras
    waveHdr.dwBufferLength = numMuestras * sizeof(short); // Tamaño del buffer
    waveHdr.dwFlags = 0;
 
    // Preparar el encabezado
    waveOutPrepareHeader(hWaveOut, &waveHdr, sizeof(WAVEHDR));
 
    // Enviar las muestras al dispositivo de audio
    waveOutWrite(hWaveOut, &waveHdr, sizeof(WAVEHDR));
 
    // Esperar a que termine la reproducción
    while (!(waveHdr.dwFlags & WHDR_DONE)) {
        Sleep(100);
    }
 
    // Limpiar
    waveOutUnprepareHeader(hWaveOut, &waveHdr, sizeof(WAVEHDR));
    waveOutClose(hWaveOut);
}
 
int main() {
    const DWORD numMuestras = 44100; // 1 segundo de audio
    short* muestras = new short[numMuestras];
 
    // Generar una onda senoidal simple
    for (DWORD i = 0; i < numMuestras; ++i) {
        muestras = (short)(32767 * sin(2 * 3.14159 * 440 * (i / 44100.0))); // 440 Hz
    }
 
    // Reproducir el sonido directamente
    reproducirSonidoDirectamente(muestras, numMuestras);
 
    delete[] muestras;
    return 0;
}

Explicación



1. Configuración del formato de audio: Se define el formato de audio utilizando `WAVEFORMATEX`, especificando parámetros como la frecuencia de muestreo y el número de canales.

2. Abrir el dispositivo de audio: Se utiliza `waveOutOpen` para abrir el dispositivo de audio.

3. Preparar el buffer de audio: Se prepara un `WAVEHDR` que contiene las muestras de audio.

4. Enviar las muestras: Se envían las muestras al dispositivo de audio con `waveOutWrite`.

5. Esperar a que termine la reproducción: Se utiliza un bucle para esperar hasta que la reproducción haya terminado.

6. Limpiar: Se deshace la preparación del encabezado y se cierra el dispositivo de audio.

Solución para la distorsión al procesar muestras



La distorsión que experimentas al multiplicar o sumar muestras de audio por un número no entero (como 0.5) puede deberse a varios factores:

1. Clipping: Si las muestras de audio originales tienen un rango de valores (por ejemplo, de -32768 a 32767 para audio de 16 bits), multiplicar por un número que no mantenga los valores dentro de este rango puede causar [i]clipping. Por ejemplo, si multiplicas por 2, los valores pueden exceder 32767, lo que resulta en distorsión.

2. Normalización: Cuando procesas audio, es importante normalizar las muestras después de aplicar cualquier operación. Por ejemplo, si multiplicas por 0.5, asegúrate de que los valores resultantes estén dentro del rango permitido.

3. Tipo de datos: Asegúrate de que estás utilizando el tipo de datos adecuado para las muestras. Si trabajas con enteros de 16 bits, considera usar un tipo de datos de punto flotante (como `float`) para realizar cálculos intermedios y luego convertir de nuevo a enteros al enviar a la tarjeta de sonido.

Ejemplo de normalización



1
2
3
for (DWORD i = 0; i < numMuestras; ++i) {
    muestras[i] = (short)(32767 * sin(2 * 3.14159 * 440 * (i / 44100.0)) * 0.5); // Multiplicando por 0.5
}

Asegúrate de que el resultado de la multiplicación no exceda el rango de 16 bits.

¡Encantado de ayudarte, Jesús!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar