Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdint.h>
- #include <Windows.h>
- EXTERN_C {
- #include <libavformat/avformat.h>
- #include <libavcodec/avcodec.h>
- };
- #include <AL/al.h>
- #include <AL/alc.h>
- #define AL_BUFFER_MAX 6
- #define MAX_AUDIOQ_SIZE (10 * 16 * 1024)
- #define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio
- #define FILE_LOCATION "test.wav"
- //aiff = s16
- struct AudioFile
- {
- AVFormatContext* fmtCtx;
- AVCodecContext* codecCtx;
- AVCodec* codec;
- AVStream* stream;
- unsigned int frequency;
- unsigned int channels;
- unsigned int sampleRate;
- unsigned int bitRate;
- unsigned int format;
- ALuint ALSource;
- ALuint ALBuffer[AL_BUFFER_MAX];
- ALuint ALCurrentBuffer;
- };
- void printAlError(ALenum alError)
- {
- printf("[OpenAL] The error is 0x%X (", alError);
- switch(alError) {
- case AL_INVALID_NAME:
- printf("AL_INVALID_NAME");
- break;
- case AL_INVALID_ENUM:
- printf("AL_INVALID_ENUM");
- break;
- case AL_INVALID_VALUE:
- printf("AL_INVALID_VALUE");
- break;
- case AL_INVALID_OPERATION:
- printf("AL_INVALID_OPERATION");
- break;
- case AL_OUT_OF_MEMORY:
- printf("AL_OUT_OF_MEMORY");
- break;
- default:
- printf("unknown");
- }
- printf(")\n");
- }
- int bufferFrame(AudioFile* af, ALuint bufferID)
- {
- int err = 0;
- ALenum alError;
- int frameComplete = 0;
- int encBytesProcessed = 0;
- int dataSize = 0;
- AVPacket *packet = (AVPacket*)malloc(sizeof(AVPacket));
- AVFrame *decodedFrame = NULL;
- av_init_packet(packet);
- err = av_read_frame(af->fmtCtx, packet);
- if (err)
- printf("[FFMPEG] There was an error reading the frame\n");
- while(!frameComplete)
- {
- if(!decodedFrame)
- {
- if(!(decodedFrame = avcodec_alloc_frame()))
- printf("[FFMPEG] Run out of memory, stop the streaming\n");
- }
- else
- {
- avcodec_get_frame_defaults(decodedFrame);
- }
- encBytesProcessed += avcodec_decode_audio4(af->codecCtx, decodedFrame, &frameComplete, packet);
- if (frameComplete)
- {
- dataSize = av_samples_get_buffer_size(NULL, af->codecCtx->channels, decodedFrame->nb_samples, af->codecCtx->sample_fmt, 0);
- if (af->format == AL_FORMAT_MONO16)
- {
- alBufferData(bufferID,af->format, *decodedFrame->data, dataSize, decodedFrame->sample_rate/2);
- }
- else
- {
- alBufferData(bufferID,af->format, decodedFrame->data, dataSize, decodedFrame->sample_rate);
- }
- av_free_packet(packet);
- av_free(decodedFrame);
- if((alError = alGetError()) != AL_NO_ERROR) {
- printf("[OpenAL] Error while buffering.\n");
- printAlError(alError);
- }
- }
- }
- return 1;
- }
- int main()
- {
- ALCcontext* ALcontext;
- ALCdevice* ALdevice;
- //Initalise OpenAL
- //==========================================================
- printf("[OpenAL] Opening OpenAL\n");
- ALdevice = alcOpenDevice(NULL);
- if (!ALdevice)
- printf("[OpenAL] Device could not be opened\n");
- ALcontext = alcCreateContext(ALdevice, NULL);
- alcMakeContextCurrent(ALcontext);
- if(!ALcontext)
- printf("[OpenAL] Counld not create OpenAL Context\n");
- ALCint nummono, numstereo;
- alcGetIntegerv(ALdevice, ALC_MONO_SOURCES, 1, &nummono);
- alcGetIntegerv(ALdevice, ALC_STEREO_SOURCES, 1, &numstereo);
- printf("[OpenAL] Audio Device %s\n", alcGetString( NULL, ALC_DEVICE_SPECIFIER ));
- printf("[OpenAL] Max mono sources: %d\n", nummono);
- printf("[OpenAL] Max stereo sources: %d\n", numstereo);
- alListener3f(AL_POSITION, 0.0f, 0.0f, 0.0f);
- //==========================================================
- //Inislaise AVcodec and AVformat
- //==========================================================
- printf("[FFMPEG] registering Codecs\n");
- avcodec_register_all();
- av_register_all();
- //==========================================================
- //Initalise file
- //==========================================================
- printf("[FFMPEG] Inisalising Audio File\n");
- AudioFile* audioTest = new AudioFile;
- alGenBuffers(AL_BUFFER_MAX, audioTest->ALBuffer);
- alGenSources(1, &audioTest->ALSource);
- alSourcei(audioTest->ALSource, AL_SOURCE_RELATIVE, AL_TRUE);
- alSourcei(audioTest->ALSource, AL_ROLLOFF_FACTOR, 0);
- audioTest->fmtCtx = avformat_alloc_context();
- if(!audioTest->fmtCtx)
- printf("[FFMPEG] Could not create AVformat Context\n");
- //==========================================================
- //load file
- //==========================================================
- printf("[FFMPEG] loading Audio File %s\n", FILE_LOCATION);
- int err;
- //open the actual file
- err = avformat_open_input(&audioTest->fmtCtx, FILE_LOCATION, NULL, NULL);
- if (err)
- printf("[FFMPEG] avformat_open_input returned an error %d\n", err);
- //obtain infomation about the stream
- err = avformat_find_stream_info(audioTest->fmtCtx, NULL);
- if (err)
- printf("[FFMPEG] avformat_find_stream_info returned an error %d\n", err);
- printf("[FFMPEG] Finding Audio Stream\n");
- //obtain the stream
- AVStream* AVaudioStream = NULL;
- for(int i = 0; i < audioTest->fmtCtx->nb_streams; i++)
- {
- if(audioTest->fmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
- {
- AVaudioStream = audioTest->fmtCtx->streams[i];
- break;
- }
- }
- //==========================================================
- //open the codec
- //=========================================================
- printf("[FFMPEG] Finding and Opening Codec\n");
- audioTest->codecCtx = AVaudioStream->codec;
- audioTest->codec = avcodec_find_decoder(audioTest->codecCtx->codec_id);
- err = avcodec_open2(audioTest->codecCtx, audioTest->codec, NULL);
- if(err)
- printf("[FFMPEG] avcodec_open2 returned an error %d\n", err);
- //=========================================================
- //print info
- //=========================================================
- printf("[FFMPEG] filename = %s\n", audioTest->fmtCtx->filename);
- printf("[FFMPEG] Channels in Stream = %d\n", audioTest->codecCtx->channels);
- printf("[FFMPEG] Codec Type = %s\n", audioTest->codecCtx->codec->long_name);
- printf("[FFMPEG] Sample Rate = %d\n", audioTest->codecCtx->sample_rate);
- printf("[FFMPEG] bit Rate = %d\n", audioTest->codecCtx->bit_rate);
- printf("[FFMPEG] block Alignment = %d\n", audioTest->codecCtx->block_align);
- printf("[FFMPEG] bits Per Sample = %d\n", audioTest->codecCtx->bits_per_raw_sample);
- printf("[FFMPEG] data format = %s\n", av_get_sample_fmt_name(audioTest->codecCtx->sample_fmt));
- //=========================================================
- //setting audio format
- //=========================================================
- printf("[FFMPEG] setting audio format\n");
- audioTest->sampleRate = audioTest->codecCtx->sample_rate;
- audioTest->channels = audioTest->codecCtx->channels;
- audioTest->bitRate = audioTest->codecCtx->bit_rate; //aparently this is always 16bit
- audioTest->format = 0;
- audioTest->stream = AVaudioStream;
- switch(audioTest->channels)
- {
- case 1:
- {
- audioTest->format = AL_FORMAT_MONO16;
- }
- case 2:
- {
- audioTest->format = AL_FORMAT_STEREO16;
- }
- case 4:
- {
- if (alIsExtensionPresent("AL_EXT_MCFORMATS"))
- {
- audioTest->format = alGetEnumValue("AL_FORMAT_QUAD16");
- }
- }
- case 6:
- {
- if (alIsExtensionPresent("AL_EXT_MCFORMATS"))
- {
- audioTest->format = alGetEnumValue("AL_FORMAT_51CHN16");
- }
- }
- }
- //=========================================================
- //stream audio
- //=========================================================
- ALenum alError;
- int bufferProc = 0;
- int totalBProc = 0;
- ALint queuedBuffers = 0, state = 0;
- printf("[Program] Preloading buffers\n");
- for(int i = 0; i < AL_BUFFER_MAX; i++)
- {
- bufferFrame(audioTest, audioTest->ALBuffer[i]);
- }
- alSourceQueueBuffers(audioTest->ALSource, AL_BUFFER_MAX, audioTest->ALBuffer);
- alSourcePlay(audioTest->ALSource);
- if((alError = alGetError()) != AL_NO_ERROR) {
- printf("[OpenAL] Error starting the stream.\n");
- printAlError(alError);
- }
- while(1)
- {
- alGetSourcei(audioTest->ALSource, AL_BUFFERS_PROCESSED, &bufferProc);
- totalBProc += bufferProc;
- while(bufferProc)
- {
- audioTest->ALCurrentBuffer = 0;
- alSourceUnqueueBuffers(audioTest->ALSource, 1, &audioTest->ALCurrentBuffer);
- bufferFrame(audioTest, audioTest->ALCurrentBuffer);
- alSourceQueueBuffers(audioTest->ALSource, 1, &audioTest->ALCurrentBuffer);
- bufferProc--;
- }
- alGetSourcei(audioTest->ALSource, AL_SOURCE_STATE, &state);
- if (state != AL_PLAYING)
- {
- // If there are Buffers in the Source Queue then the Source was starved of audio
- // data, so needs to be restarted (because there is more audio data to play)
- alGetSourcei(audioTest->ALSource, AL_BUFFERS_QUEUED, &queuedBuffers);
- if (queuedBuffers)
- {
- alSourcePlay(audioTest->ALSource);
- }
- else
- {
- // Finished playing
- break;
- }
- }
- }
- alSourceStop(audioTest->ALSource);
- //=========================================================
- avcodec_close(audioTest->codecCtx);
- av_free(audioTest->codecCtx);
- av_free(audioTest->fmtCtx);
- alcMakeContextCurrent(NULL);
- alcDestroyContext(ALcontext);
- alcCloseDevice(ALdevice);
- delete audioTest;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement