Closed fatalfeel closed 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. */
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. */
LOAD_PROC(device, alcGetStringiSOFT);
LOAD_PROC(device, alcResetDeviceSOFT);
/* 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;
}
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.
close this issue
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); }
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, '.');