kcat / openal-soft

OpenAL Soft is a software implementation of the OpenAL 3D audio API.
Other
2.13k stars 522 forks source link

insert head phone examples alhrtf error #44

Closed fatalfeel closed 8 years ago

fatalfeel commented 8 years ago

root@stone-linux:~/openal-soft-172# ./alhrtf -hrtf default-44100 /root/openal-soft-172/hsound.wav

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if insert head phone if(usedefaults) { //vector_al_string flist = SearchDataFiles(".mhr", "openal/hrtf");//for my setting only flist = SearchDataFiles(".mhr", "/home/feelthat/openal-soft-172/hrtf"); VECTOR_FOR_EACH_PARAMS(al_string, flist, AddFileEntry, &list); ---> will do twice problem VECTOR_DEINIT(flist); }

  1. from aluInitRenderer
  2. from alcGetIntegerv(device, ALC_NUM_HRTF_SPECIFIERS_SOFT, 1, &num_hrtf);

then num_hrtf will return 0; //error

need fix it on static void AddFileEntry(vector_HrtfEntry list, al_string filename) label set here done: ext = strrchr(name, '.');

fatalfeel commented 8 years ago

//my alhrtf.c //http://fatalfeel.blogspot.tw/2013/09/openal-hrtf-3d-sound.html /*

/* This file contains an example for selecting an HRTF. */

include

include

include

include

include

include

include "AL/al.h"

include "AL/alc.h"

include "AL/alext.h"

include "common/alhelpers.h"

include "common/sdl_sound.h"

ifndef M_PI

define M_PI (3.14159265358979323846)

endif

static LPALCGETSTRINGISOFT alcGetStringiSOFT; static LPALCRESETDEVICESOFT alcResetDeviceSOFT; static unsigned char* raw_data = NULL;

struct WHEADER { unsigned char riff[4]; // RIFF string unsigned int overall_size ; // overall size of file in bytes unsigned char wave[4]; // WAVE string unsigned char fmt_chunk_marker[4]; // fmt string with trailing null char unsigned int length_of_fmt; // length of the format data unsigned int format_type; // format type. 1-PCM, 3- IEEE float, 6 - 8bit A law, 7 - 8bit mu law unsigned int channels; // no.of channels unsigned int sample_rate; // sampling rate (blocks per second) unsigned int byterate; // SampleRate * NumChannels * BitsPerSample/8 unsigned int block_align; // NumChannels * BitsPerSample/8 unsigned int bits_per_sample; // bits per sample, 8- 8bits, 16- 16 bits etc unsigned char data_chunk_header [4]; // DATA string or FLLR string unsigned int data_size; // NumSamples * NumChannels * BitsPerSample/8 - size of the next chunk that will be read };

static ALuint LoadSound(char _filename) { ALuint al_buffer = 0; int read; char format_name[8] = {0}; unsigned char buffer4[4]; unsigned char buffer2[2]; struct WHEADER header; long num_samples; long size_of_each_sample; float duration_inseconds; ALenum format; FILE ptr;

 ptr = fopen(filename, "rb");
 if (ptr == NULL)
 {
    printf("Error opening file\n");
    return al_buffer;
 }

 // read header parts
 read = fread(header.riff, sizeof(header.riff), 1, ptr);
 printf("(1-4): %s \n", header.riff);

 read = fread(buffer4, sizeof(buffer4), 1, ptr);
 printf("%u %u %u %u\n", buffer4[0], buffer4[1], buffer4[2], buffer4[3]);

 // convert little endian to big endian 4 byte int
 header.overall_size  = buffer4[0] | (buffer4[1]<<8) | (buffer4[2]<<16) | (buffer4[3]<<24);
 printf("(5-8) Overall size: bytes:%u, Kb:%u \n", header.overall_size, header.overall_size/1024);

 read = fread(header.wave, sizeof(header.wave), 1, ptr);
 printf("(9-12) Wave marker: %s\n", header.wave);

 read = fread(header.fmt_chunk_marker, sizeof(header.fmt_chunk_marker), 1, ptr);
 printf("(13-16) Fmt marker: %s\n", header.fmt_chunk_marker);

 read = fread(buffer4, sizeof(buffer4), 1, ptr);
 printf("%u %u %u %u\n", buffer4[0], buffer4[1], buffer4[2], buffer4[3]);

 // convert little endian to big endian 4 byte integer
 header.length_of_fmt = buffer4[0] | (buffer4[1] << 8) | (buffer4[2] << 16) | (buffer4[3] << 24);
 printf("(17-20) Length of Fmt header: %u \n", header.length_of_fmt);

 read = fread(buffer2, sizeof(buffer2), 1, ptr); printf("%u %u \n", buffer2[0], buffer2[1]);

 header.format_type = buffer2[0] | (buffer2[1] << 8);
 if (header.format_type == 1)
     strcpy(format_name,"PCM");
 else if (header.format_type == 6)
     strcpy(format_name, "A-law");
 else if (header.format_type == 7)
     strcpy(format_name, "Mu-law");

 printf("(21-22) Format type: %u %s \n", header.format_type, format_name);

 read = fread(buffer2, sizeof(buffer2), 1, ptr);
 printf("%u %u \n", buffer2[0], buffer2[1]);

 header.channels = buffer2[0] | (buffer2[1] << 8);
 printf("(23-24) Channels: %u \n", header.channels);

 read = fread(buffer4, sizeof(buffer4), 1, ptr);
 printf("%u %u %u %u\n", buffer4[0], buffer4[1], buffer4[2], buffer4[3]);

 header.sample_rate = buffer4[0] |(buffer4[1] << 8) |(buffer4[2] << 16) | (buffer4[3] << 24);
 printf("(25-28) Sample rate: %u\n", header.sample_rate);

 read = fread(buffer4, sizeof(buffer4), 1, ptr);
 printf("%u %u %u %u\n", buffer4[0], buffer4[1], buffer4[2], buffer4[3]);

 header.byterate  = buffer4[0] |(buffer4[1] << 8) | (buffer4[2] << 16) | (buffer4[3] << 24);
 printf("(29-32) Byte Rate: %u , Bit Rate:%u\n", header.byterate, header.byterate*8);

 read = fread(buffer2, sizeof(buffer2), 1, ptr);
 printf("%u %u \n", buffer2[0], buffer2[1]);

 header.block_align = buffer2[0] | (buffer2[1] << 8);
 printf("(33-34) Block Alignment: %u \n", header.block_align);

 read = fread(buffer2, sizeof(buffer2), 1, ptr);
 printf("%u %u \n", buffer2[0], buffer2[1]);

 header.bits_per_sample = buffer2[0] | (buffer2[1] << 8);
 printf("(35-36) Bits per sample: %u \n", header.bits_per_sample);

 read = fread(header.data_chunk_header, sizeof(header.data_chunk_header), 1, ptr);
 printf("(37-40) Data Marker: %s \n", header.data_chunk_header);

 read = fread(buffer4, sizeof(buffer4), 1, ptr);
 printf("%u %u %u %u\n", buffer4[0], buffer4[1], buffer4[2], buffer4[3]);

 header.data_size = buffer4[0] | (buffer4[1] << 8) | (buffer4[2] << 16) |   (buffer4[3] << 24 );
 printf("(41-44) Size of data chunk: %u \n", header.data_size);

 // calculate no.of samples
 num_samples = (8 * header.data_size) / (header.channels * header.bits_per_sample);
 printf("Number of samples:%lu \n", num_samples);

 size_of_each_sample = (header.channels * header.bits_per_sample) / 8;
 printf("Size of each sample:%ld bytes\n", size_of_each_sample);

 // calculate duration of file
 duration_in_seconds = (float) header.overall_size / header.byterate;
 printf("Approx.Duration in seconds=%f\n", duration_in_seconds);

 // read each sample from data chunk if PCM
 if (header.format_type == 1)
 {
     raw_data   = malloc(size_of_each_sample*num_samples);
     read           = fread(raw_data, size_of_each_sample*num_samples, 1, ptr);
     if(header.bits_per_sample == 8)
     {
         if(header.channels == 1)
             format = AL_FORMAT_MONO8;
         else if(header.channels == 2)
             format = AL_FORMAT_STEREO8;
     }
     else if(header.bits_per_sample == 16)
     {
         if(header.channels == 1)
             format = AL_FORMAT_MONO16;
         else if(header.channels == 2)
             format = AL_FORMAT_STEREO16;
     }
     alGenBuffers(1, &al_buffer);
     alBufferData(al_buffer, format, raw_data, size_of_each_sample*num_samples, header.sample_rate);
 } //  if (header.format_type == 1)

 printf("Closing file..\n");
 fclose(ptr);

return al_buffer;

}

int main(int argc, char *argv) { ALCdevice device; ALuint source, buffer; char soundname; char hrtfname; ALCint hrtf_state; ALCint num_hrtf; ALdouble angle; ALenum state;

/* Print out usage if no file was specified */
if(argc < 2 || (strcmp(argv[1], "-hrtf") == 0 && argc < 4))
{
    fprintf(stderr, "Usage: %s [-hrtf <name>] <soundfile>\n", argv[0]);
    return 1;
}

/* Initialize OpenAL with the default device, and check for HRTF support. */
if(InitAL() != 0)
    return 1;

if(strcmp(argv[1], "-hrtf") == 0)
{
    hrtfname = argv[2];
    soundname = argv[3];
}
else
{
    hrtfname = NULL;
    soundname = argv[1];
}

device = alcGetContextsDevice(alcGetCurrentContext());
if(!alcIsExtensionPresent(device, "ALC_SOFT_HRTF"))
{
    fprintf(stderr, "Error: ALC_SOFT_HRTF not supported\n");
    CloseAL();
    return 1;
}

/* Define a macro to help load the function pointers. */

define LOAD_PROC(d, x) ((x) = alcGetProcAddress((d), #x))

LOAD_PROC(device, alcGetStringiSOFT);
LOAD_PROC(device, alcResetDeviceSOFT);

undef LOAD_PROC

/* Enumerate available HRTFs, and reset the device using one. */
alcGetIntegerv(device, ALC_NUM_HRTF_SPECIFIERS_SOFT, 1, &num_hrtf);
if(!num_hrtf)
    printf("No HRTFs found\n");
else
{
    ALCint attr[5];
    ALCint index = -1;
    ALCint i;

    printf("Available HRTFs:\n");
    for(i = 0;i < num_hrtf;i++)
    {
        const ALCchar *name = alcGetStringiSOFT(device, ALC_HRTF_SPECIFIER_SOFT, i);
        printf("    %d: %s\n", i, name);

        /* Check if this is the HRTF the user requested. */
        if(hrtfname && strcmp(name, hrtfname) == 0)
            index = i;
    }

    i = 0;
    attr[i++] = ALC_HRTF_SOFT;
    attr[i++] = ALC_TRUE;
    if(index == -1)
    {
        if(hrtfname)
            printf("HRTF \"%s\" not found\n", hrtfname);
        printf("Using default HRTF...\n");
    }
    else
    {
        printf("Selecting HRTF %d...\n", index);
        attr[i++] = ALC_HRTF_ID_SOFT;
        attr[i++] = index;
    }
    attr[i] = 0;

    if(!alcResetDeviceSOFT(device, attr))
        printf("Failed to reset device: %s\n", alcGetString(device, alcGetError(device)));
}

/* Check if HRTF is enabled, and show which is being used. */
alcGetIntegerv(device, ALC_HRTF_SOFT, 1, &hrtf_state);
if(!hrtf_state)
    printf("HRTF not enabled!\n");
else
{
    const ALchar *name = alcGetString(device, ALC_HRTF_SPECIFIER_SOFT);
    printf("HRTF enabled, using %s\n", name);
}
fflush(stdout);

/* Load the sound into a buffer. */
buffer = LoadSound(soundname);
if(!buffer)
{
    CloseAL();
    return 1;
}

/* Create the source to play the sound with. */
source = 0;
alGenSources(1, &source);
alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE);
alSource3f(source, AL_POSITION, 0.0f, 0.0f, -1.0f);
alSourcei(source, AL_BUFFER, buffer);
assert(alGetError()==AL_NO_ERROR && "Failed to setup sound source");

/* Play the sound until it finishes. */
angle = 0.0;
alSourcePlay(source);
do {
    al_nssleep(10000000);

    /* Rotate the source around the listener by about 1/4 cycle per second.
     * Only affects mono sounds.
     */
    angle += 0.01 * M_PI * 0.5;
    alSource3f(source, AL_POSITION, (ALfloat)sin(angle), 0.0f, -(ALfloat)cos(angle));

    alGetSourcei(source, AL_SOURCE_STATE, &state);
} while(alGetError() == AL_NO_ERROR && state == AL_PLAYING);

/* All done. Delete resources, and close OpenAL. */
alDeleteSources(1, &source);
alDeleteBuffers(1, &buffer);

CloseAL();

free(raw_data);

return 0;

}

kcat commented 8 years ago

Unfortunately I don't quite understand what you're getting at. If alcGetIntegerv(device, ALC_NUM_HRTF_SPECIFIERS_SOFT, 1, &num_hrtf); is giving back num_hrtf as 0, then no HRTFs were found.

VECTOR_FOR_EACH_PARAMS(al_string, flist, AddFileEntry, &list); happening twice is fine, because it's appending to list.

I don't understand this change:

//vector_al_string flist = SearchDataFiles(".mhr", "openal/hrtf");
flist = SearchDataFiles(".mhr", "/home/feelthat/openal-soft-172/hrtf");

This should give a compile error since flist isn't being declared, and you're also hard-coding the default search paths for HRTFs to a specific place in your home directory instead of using the XDG standard paths. If you want a different path for mhr files, you can instead specify it in the config file -- create ~/.config/alsoft.conf and add the lines

[general]
hrtf-paths = /home/feelthat/openal-soft-172/hrtf,

And of course make sure you have mhr files there.

fatalfeel commented 8 years ago

close this issue