# data[].attributes.body
Fichero 'Makefile' para compilar los archivos de ejemplo.

# data[].attributes.attachment_link.title
Makefile basic_sin, basic_sin2 - Codepad

# data[].attributes.attachment_link.description
Makefile to compile the basic_sin and basic_sin2 examples. It should work as is on FreeBSD and Linux. If it doesn't work for Linux just change: CC...

# data[].attributes.body
Variante de 'basic_sin' que genera la señal fuera de la función 'callback'.

# data[].attributes.attachment_link.readable_text
#include <iostream> #include <cmath> #include <SDL2/SDL.h> const double TWOPI = 2 * M_PI; // Although this struct is not required it makes easier // moving data into the audio buffer. struct AudioData { Uint8 *data; Uint32 length; }; double phase = 0.0; double phase_incr = 0.0; // // Genereates a 'sin' signal 'num_samples' long. It stores the // amplitude values into the 'out_signal' buffer, normalized // in the range -1.0 .. 1.0 // float *GenSignal(unsigned long num_samples, float volume) { // Create a buffer to store the signal in the range of -1.0 .. 1.0 float *out_signal = new float[num_samples]; if (out_signal == nullptr) std::cerr << "GenSignal(): No se pudo reservar memoria\n"; // Generate the sample values and store them in the signal buffer for (int n = 0; n < num_samples; n++) { out_signal[n] = volume * sin(phase); phase += phase_incr; if (phase >= TWOPI) phase -= TWOPI; } // Return the signal buffer with the calculated values. return out_signal; } // Re-escala la señal al formato de audio 16-bit con signo // It just multiplies each sample signal by the 'scale' value Sint16 *ScaleSignal(float *out_amp, unsigned long num_samples, Sint16 scale) { // Create a buffer to store the scaled values in a signed 16-bit format Sint16 *scaled_signal = new Sint16[num_samples]; // Scale the signal value and store it into the signed 16-bit buffer. for (int n=0; n < num_samples; n++) { scaled_signal[n] = scale * out_amp[n]; } // Return the signed 16-bit buffer with the scaled values. return scaled_signal; } // ----- Audio Callback ----- // // This time we don't perform any format conversion. We don't care // what the audio data format is in. We just send it to the audio // buffer device, like we did in the play_wav.cc example. // void AudioCallback(void *userdata, Uint8 *stream, int stream_length) { // The 'userdata' contains our AudioData information. AudioData *audio = (AudioData*)userdata; // If there are no more bytes in the audio, we are finished. // This time we are dealing with absolute bytes, not number // of samples. if (audio->length == 0) { return; } // Adjust the length buffer to manipulate according to how many // bytes still need to be moved (are we at the end of audio?). Uint32 length = (Uint32) stream_length; length = length > audio->length ? audio->length : length; // Copy the audio data from our own buffer (audio->data) to // the audio buffer device (stream). SDL_memcpy(stream, audio->data, length); // We just copied 'length' bytes of data. We need to adjust the // data pointer (audio->data) to point to the correct location // next time the callback gets called. Also, we need to update // the number of bytes still remaining (audio->length). audio->length -= length; audio->data+= length; } // // ----- InitAudio() ----- // // Initializes the SDL library for audio and requests an audio // device with our desired audio format specs. // // Returns // // A valid audio device ID SDL_AudioDeviceID InitAudio(int sample_rate, AudioData *audio, SDL_AudioSpec *want, SDL_AudioSpec *have) { SDL_Init(SDL_INIT_AUDIO); want->freq = sample_rate; want->format = AUDIO_S16; want->channels = 1; want->samples = 4096; want->callback = AudioCallback; want->userdata = audio; SDL_AudioDeviceID device = SDL_OpenAudioDevice( nullptr, 0, want, have, SDL_AUDIO_ALLOW_ANY_CHANGE); if (device == 0) { return -1; } return device; } // ----- PlayAudio() ----- int PlayAudio(SDL_AudioDeviceID device, AudioData &audio) { SDL_PauseAudioDevice(device, 0); while (audio.length > 0) { SDL_Delay(100); } return 0; } // ----- CloseAudio() ----- int CloseAudio(SDL_AudioDeviceID device) { SDL_PauseAudioDevice(device, 1); SDL_CloseAudioDevice(device); SDL_Quit(); return 0; } // ----- Main Program Starts Here ----- int main() { float duration = 5; float pitch = 323; float volume = 0.8; int sample_rate = 44100; Uint32 total_samples = sample_rate * duration; // The normalized (-1.0 .. 1.0) and scaled (-32767..32767) signal buffers. float *norm_signal = nullptr; Sint16 *scaled_signal = nullptr; phase_incr = TWOPI / sample_rate * pitch; // Generate a singal in the range -1.0..+1.0 norm_signal = GenSignal(total_samples, volume); // Scale the signal to a 16-bit range (-32767..32767) scaled_signal = ScaleSignal(norm_signal, total_samples, 32768); // Now we got our signed 16-bit audio data in a buffer // Let's create the required data structures to play it. SDL_AudioSpec want, have; AudioData audio; // Ask for an audio device capable of playing 16-bit signed audio // at 'sample_rate' (44100) Hz. SDL_AudioDeviceID device = InitAudio(sample_rate, &audio, &want, &have); // We got our audio device, now set the audio data // First, the audio data points to the signal we just created. // We no longer care it's signed and 16-bit, now it's just a raw stream // of bytes. // Also, each value in our 16-bit buffer signal is 2-bytes long. // So the audio length is the total samples multiplied by 2 bytes // in each sample. audio.data = (Uint8*)scaled_signal; audio.length = total_samples*2; // Play the audio PlayAudio(device, audio); // Pause and Close the audio device. CloseAudio(device); // Free the signal buffers and safely point them to null if (norm_signal != nullptr) delete[] norm_signal; if (scaled_signal != nullptr) delete scaled_signal; norm_signal=nullptr; scaled_signal=nullptr; return 0; }

A variation of the basic_sin.cc program which no longer generates the signed 16-bit signal values in the SDL audio callback.
Instead, it generates the signal (actually two signals, a normalized signal in the range -1.0..1.0 and a scaled signal in the range -32767..32767) outside and stores it in a buffer.
The signal buffer is then copied to the audio buffer device in the SDL audio callback as raw bytes, like we did in the play_wav.cc.
I believe that's a more elegant and scalable solution.

# data[].attributes.attachment_link.description
include #include #include const double TWOPI = 2 * M_PI; // Although this struct is not required it makes easier // moving data into the audio buffer. struct AudioData { Uint8 *data; Uint32 length; }; double phase = 0.0; double phase_incr = 0.0; // // Genereates a 'sin' signal 'num_samples' long.

# data[].attributes.body
Crea una onda sinusoidal de 440Hz de frecuencia y reproduce el sonido por los altavoces. Utiliza la librería SDL2 para inicializar y reproducir el audio.

# data[].attributes.attachment_link.readable_text
/* Éste código únicamente pretende ser una referencia para mis proyectos personales. La mayor parte del código está extraído de la siguiente web: http://rerwarwar.weebly.com/sdl2-audio-init.html También he incorporado algunas ideas del libro "Basic Synth" de Daniel R. Mitchel. Cualquier atribución de copyrght pertenece a sus respectivos autores originales y no a mí. Mas info: https://www.youtube.com/watch?v=6IX6873J1Y8 */ #include "SDL2/SDL.h" #include <iostream> #include <cmath> using namespace std; const float FREQ = 440; /* the frequency we want */ const double TWOPI = 2 * M_PI; unsigned int audio_position; /* which sample we are up to */ int audio_len; /* how many samples left to play, stops when <= 0 */ float audio_frequency; /* audio frequency in cycles per sample */ float audio_volume; /* audio volume, 0 - 32767 */ double freqRad; // 2 * pi / Fs (Fs = frecuencia muestreo = 44100 en este ejemplo) double phaseIncr; // intervalo de separación entre cada sample de la onda medido en radianes. // (2 * pi / Fs) * f // // Fs = frecuencia de muestreo (44100) // f = frecuencia de la nota (440) /* Audio Callback. En esta función debemos copiar los datos que se reproducirán por el disposi tivo de audio. La idea es llenar el 'stream' proporcionado por SDL con los datos correspondientes de audio (amplitud para cada sample). NOTA: Calcular los valores de amplitud de la onda en el callback no es la mejor opción y complica el código debido a la diferencia de formatos entre el stream (bytes) y las amplitudes de la onda (16-bit). */ void MyAudioCallback(void* userdata, Uint8* stream, int len) { // Si no hay más datos a reproducir, salimos. if (audio_len == 0) { return; } // Si audio_len < len seguramente estamos al final del clip de audio // y por tanto el tamaño en bytes que falta por reproducir no es len // sino audio_len. // // Además estamos trabajando con datos de 16-bits (16-bit con signo // para las amplitudes de cada sample), y por tanto, el número de bytes // que queremos reproducir es len/2 // len = (len > audio_len ? audio_len : len/2); int i; Sint16* buf = (Sint16*)stream; double phase = 0; // Para cada sample del stream, calculamos su amplitud (-32767 - 32767) for(i = 0; i < len; i++) { buf[i] = audio_volume * sin(phaseIncr * audio_position); audio_position++; } // Actualizamos cuantos bytes quedan por reproducir audio_len -= len; return; } // ----- Main Program Starts Here ----- int main(int nargs, char *args[]) { // Inicialización de Audio con SDL2 if(SDL_Init(SDL_INIT_AUDIO)) { cout << "[SDL] Failed to initialize: " << SDL_GetError() << "\n"; return 1; } // Para abrir el dispositivo de audio creamos dos estructuras SDL_AudioSpec: // // want: Especifica el formato de audio que 'queremos' usar // have: Lo devuelve SDL y contiene los valores del formato obtenido por el dispositivo de audio abierto // SDL_AudioSpec want, have; want.freq = 44100; // Frecuencia de muestreo (sample rate) want.format = AUDIO_S16; // Formato y precisión para la amplitud // 16-bit con signo, cada sample tendrá una amplitud entre -32768 y 32767 want.channels = 1; // Mono, (estereo complica la programación) want.samples = 512; // Si este valor es bajo permite duraciones muy cortas want.callback = MyAudioCallback; // El 'callback' que llamará SDL para copiar los datos de audio (y en consecuencia reproducirlo) // Abre el dispositivo de audio con los parametros que deseamos // A partir de aquí, 'have' tendrá los valores válidos que el dispositivo nos // deja usar. SDL_AudioDeviceID dev = SDL_OpenAudioDevice(NULL, 0, &want, &have, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); audio_position = 0; float volume = 0.5; // 0.0 .. 1.0 float frequency = FREQ; // Nota a tocar en Hz float duration = 5; // Duración del sonido en segundos // Para hacer un poco más completo el programa permitimos cambiar // la nota, el volumen y la duración al invocar el programa. if (nargs > 1) frequency = atof(args[1]); if (nargs > 2) volume = atof(args[2]); if (nargs > 3) duration = atof(args[3]); // El número total de samples será la frecuencia de muestreo multiplicado por // la duración del sonido. audio_len = have.freq * duration; // Escalamos el volumen al rango de 16-bits audio_volume = 32767 * volume; // Arriba en la definición de las variables se explica estos valores. freqRad = TWOPI / have.freq; phaseIncr = freqRad * frequency; // Reproducimos el sonido SDL_PauseAudioDevice(dev, 0); // Si no se realiza este bucle se reproduciría una parte del sonido // y enseguida saldríamos del programa (parecido a la necesidad de un game loop) while(audio_len > 0) { SDL_Delay(100); } // Cerramos el dispositivo de audio y salimos limpiamente de SDL SDL_CloseAudioDevice(dev); SDL_Quit(); return 0; }

Código completo que genera una onda 'sin' de 440Hz y la reproduce por el dispositivo de sonido primario. Se utiliza la librería SDL2 para la inicialización y reproducción del audio.

# data[].attributes.attachment_link.description
Éste código únicamente pretende ser una referencia para mis proyectos personales. La mayor parte del código está extraído de la siguiente web: http://rerwarwar.weebly.com/sdl2-audio-init.html También he incorporado algunas ideas del libro "Basic Synth" de Daniel R. Mitchel. Cualquier atribución de copyrght pertenece a sus respectivos autores originales y no a mí.

# data[].attributes.body
Reproduce un archivo de sonido WAV usando la librería SDL2.

# data[].attributes.attachment_link.description
Reproduce un archivo de sonido WAV usando la librería SDL2