Alexiy
Alexiy

Reputation: 2030

Can I produce a synthetic sound using OpenAL?

I'm learning Java OpenAL bindings (version 3.1.2) and I would like to make a custom sound (synthetic).

I've searched the web for this, but I haven't found what I'm looking for - all tutorials show how to play sound files.

I want to make an app in which I can "program" the sounds. So far I understand that the data of sound files is being passed into a buffer. Can I figure out what data must be put in those buffers in my case?

Here is my application's base. It is written in Groovy.

package alexiy.openal

import javafx.application.Application
import javafx.event.ActionEvent
import javafx.event.EventHandler
import javafx.scene.Scene
import javafx.scene.control.Button
import javafx.scene.layout.GridPane
import javafx.stage.Stage
import javafx.stage.WindowEvent
import org.lwjgl.BufferUtils
import org.lwjgl.openal.*
import org.lwjgl.system.libc.LibCStdlib

import java.nio.ByteBuffer
import java.nio.IntBuffer



class OALP extends Application {
    static ALCapabilities alCapabilities;
    static ALCCapabilities alcCapabilities;

    @Override
    void start(Stage primaryStage) throws Exception {

        String deviceinfo= ALC10.alcGetString(0,EnumerateAllExt.ALC_DEFAULT_ALL_DEVICES_SPECIFIER);

        println('Device: '+deviceinfo)
        long device= ALC10.alcOpenDevice(deviceinfo);
        if(device==0) throw new RuntimeException("Couldn't find such device")
        println device

        int[] attributes=[ALC11.ALC_STEREO_SOURCES,1,0]
        long context=ALC10.alcCreateContext(device,attributes)
        println context
        boolean b=ALC10.alcMakeContextCurrent(context)
        alcCapabilities= ALC.createCapabilities(device)
        AL.createCapabilities(alcCapabilities)
        alCapabilities= AL.getCapabilities()
        GridPane gridPane=new GridPane();
        gridPane.setVgap(6)
        gridPane.setHgap(6)
        Scene scene=new Scene(gridPane,300,100)
        primaryStage.setScene(scene)
        Button decode=new Button("Decode")
        decode.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            void handle(ActionEvent event) {
                File track=new File("Fields.ogg")

            }
        })
        gridPane.add(decode,0,0)
        primaryStage.show();
        primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
            @Override
            void handle(WindowEvent event) {
                ALC10.alcMakeContextCurrent(0)
                ALC10.alcDestroyContext(context)
                ALC10.alcCloseDevice(device)
            }
        })
        int seconds=4;
        int samplerate=44100
        int buffersiz=seconds*samplerate
        int buffer=AL10.alGenBuffers()
        float freq=1
        float incr=0.1f
//        IntBuffer intBuffer=IntBuffer.allocate(buffersiz)
        ByteBuffer intBuffer=LibCStdlib.malloc(buffersiz)
        for (int i = 0; i < buffersiz; i++) {
            intBuffer.put(i,(byte) (32760 * Math.sin( 2 * 3.14 *freq)/samplerate * i))
            freq+=incr
            if (100.0 > freq || freq > 5000.0) {

                incr *= -1.0f;
            }
        }
        AL10.alBufferData(buffer,AL10.AL_FORMAT_STEREO16, intBuffer,300)
        LibCStdlib.free(intBuffer)
        int souirce=AL10.alGenSources()
        AL10.alSourcei(souirce,AL10.AL_BUFFER,buffer)
        AL10.alSourcePlay(souirce)
        Thread.sleep(3000)
        printError()
    }

    static void printError(){ println AL10.alGetString(AL10.alGetError())}
}

Upvotes: 1

Views: 988

Answers (1)

Scott Stensland
Scott Stensland

Reputation: 28285

Here is some c code where I use OpenAL to render audio which is synthesized locally from calling sin function in a loop ... translating to java should be straight forward

// sudo apt-get install libopenal-dev  #  install OpenAL on linux

// gcc -o openal_play_monday   openal_play_monday.c  -lopenal -lm

#include <stdio.h>
#include <stdlib.h>    // gives malloc
#include <math.h>
#include <unistd.h>    // gives sleep


#ifdef __APPLE__
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#elif __linux
#include <AL/al.h>
#include <AL/alc.h>
#endif

ALCdevice  * openal_output_device;
ALCcontext * openal_output_context;

ALuint internal_buffer;
ALuint streaming_source[1];

int al_check_error(const char * given_label) {

    ALenum al_error;
    al_error = alGetError();

    if(AL_NO_ERROR != al_error) {

        printf("ERROR - %s  (%s)\n", alGetString(al_error), given_label);
        return al_error;
    }
    return 0;
}

void MM_init_al() {

    const char * defname = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);

    openal_output_device  = alcOpenDevice(defname);
    openal_output_context = alcCreateContext(openal_output_device, NULL);
    alcMakeContextCurrent(openal_output_context);

    // setup buffer and source

    alGenBuffers(1, & internal_buffer);
    al_check_error("failed call to alGenBuffers");
}

void MM_exit_al() {

    ALenum errorCode = 0;

    // Stop the sources
    alSourceStopv(1, & streaming_source[0]);        //      streaming_source
    int ii;
    for (ii = 0; ii < 1; ++ii) {
        alSourcei(streaming_source[ii], AL_BUFFER, 0);
    }
    // Clean-up
    alDeleteSources(1, &streaming_source[0]);
    alDeleteBuffers(16, &streaming_source[0]);
    errorCode = alGetError();
    alcMakeContextCurrent(NULL);
    errorCode = alGetError();
    alcDestroyContext(openal_output_context);
    alcCloseDevice(openal_output_device);
}

void MM_render_one_buffer() {

    /* Fill buffer with Sine-Wave */
    // float freq = 440.f;
    float freq = 100.f;
    float incr_freq = 0.1f;

    int seconds = 4;
    // unsigned sample_rate = 22050;
    unsigned sample_rate = 44100;
    double my_pi = 3.14159;
    size_t buf_size = seconds * sample_rate;

    // allocate PCM audio buffer        
    short * samples = malloc(sizeof(short) * buf_size);

   printf("\nhere is freq %f\n", freq);
    int i=0;
    for(; i<buf_size; ++i) {
        samples[i] = 32760 * sin( (2.f * my_pi * freq)/sample_rate * i );

        freq += incr_freq;
        // incr_freq += incr_freq;
        // freq *= factor_freq;

        if (100.0 > freq || freq > 5000.0) {

            incr_freq *= -1.0f;
        }
    }

    /* upload buffer to OpenAL */
    alBufferData( internal_buffer, AL_FORMAT_MONO16, samples, buf_size, sample_rate);
    al_check_error("populating alBufferData");

    free(samples);

    /* Set-up sound source and play buffer */
    // ALuint src = 0;
    // alGenSources(1, &src);
    // alSourcei(src, AL_BUFFER, internal_buffer);
    alGenSources(1, & streaming_source[0]);
    alSourcei(streaming_source[0], AL_BUFFER, internal_buffer);
    // alSourcePlay(src);
    alSourcePlay(streaming_source[0]);

    // ---------------------

    ALenum current_playing_state;
    alGetSourcei(streaming_source[0], AL_SOURCE_STATE, & current_playing_state);
    al_check_error("alGetSourcei AL_SOURCE_STATE");

    while (AL_PLAYING == current_playing_state) {

        printf("still playing ... so sleep\n");

        sleep(1);   // should use a thread sleep NOT sleep() for a more responsive finish

        alGetSourcei(streaming_source[0], AL_SOURCE_STATE, & current_playing_state);
        al_check_error("alGetSourcei AL_SOURCE_STATE");
    }

    printf("end of playing\n");

    /* Dealloc OpenAL */
    MM_exit_al();

}   //  MM_render_one_buffer

int main() {

    MM_init_al();

    MM_render_one_buffer();
}

Upvotes: 3

Related Questions