/* ================= S_WAV_CodecOpenStream ================= */ snd_stream_t *S_WAV_CodecOpenStream(const char *filename) { snd_stream_t *rv; // Open rv = S_CodecUtilOpen(filename, &wav_codec); if(!rv) return NULL; // Read the RIFF header if(!S_ReadRIFFHeader(rv->file, &rv->info)) { S_CodecUtilClose(&rv); return NULL; } return rv; }
/* ================= S_OggOpus_CodecOpenStream ================= */ snd_stream_t *S_OggOpus_CodecOpenStream( const char *filename ) { snd_stream_t *stream; // Opus codec control structure OggOpusFile *of; // some variables used to get informations about the file const OpusHead *opusInfo; ogg_int64_t numSamples; // check if input is valid if ( !filename ) { return NULL; } // Open the stream stream = S_CodecUtilOpen( filename, &opus_codec ); if ( !stream ) { return NULL; } // open the codec with our callbacks and stream as the generic pointer of = op_open_callbacks( stream, &S_OggOpus_Callbacks, NULL, 0, NULL ); if ( !of ) { S_CodecUtilClose( &stream ); return NULL; } // the stream must be seekable if ( !op_seekable( of ) ) { op_free( of ); S_CodecUtilClose( &stream ); return NULL; } // get the info about channels and rate opusInfo = op_head( of, -1 ); if ( !opusInfo ) { op_free( of ); S_CodecUtilClose( &stream ); return NULL; } if ( opusInfo->stream_count != 1 ) { op_free( of ); S_CodecUtilClose( &stream ); Com_Printf( "Only Ogg Opus files with one stream are support\n" ); return NULL; } if ( opusInfo->channel_count != 1 && opusInfo->channel_count != 2 ) { op_free( of ); S_CodecUtilClose( &stream ); Com_Printf( "Only mono and stereo Ogg Opus files are supported\n" ); return NULL; } // get the number of sample-frames in the file numSamples = op_pcm_total( of, -1 ); // fill in the info-structure in the stream stream->info.rate = 48000; stream->info.width = OPUS_SAMPLEWIDTH; stream->info.channels = opusInfo->channel_count; stream->info.samples = numSamples; stream->info.size = stream->info.samples * stream->info.channels * stream->info.width; stream->info.dataofs = 0; // We use stream->pos for the file pointer in the compressed ogg file stream->pos = 0; // We use the generic pointer in stream for the opus codec control structure stream->ptr = of; return stream; }
static snd_stream_t *S_VORBIS_CodecOpenStream (const char *filename) { snd_stream_t *stream; OggVorbis_File *ovFile; vorbis_info *ovf_info; long numstreams; int res; stream = S_CodecUtilOpen(filename, &vorbis_codec); if (!stream) return NULL; ovFile = (OggVorbis_File *) Z_Malloc(sizeof(OggVorbis_File)); res = OV_OPEN_CALLBACKS(&stream->fh, ovFile, NULL, 0, ovc_qfs); if (res != 0) { Con_Printf("%s is not a valid Ogg Vorbis file (error %i).\n", filename, res); goto _fail; } stream->priv = ovFile; if (!ov_seekable(ovFile)) { Con_Printf("Stream %s not seekable.\n", filename); goto _fail; } ovf_info = ov_info(ovFile, 0); if (!ovf_info) { Con_Printf("Unable to get stream info for %s.\n", filename); goto _fail; } /* FIXME: handle section changes */ numstreams = ov_streams(ovFile); if (numstreams != 1) { Con_Printf("More than one (%ld) stream in %s.\n", numstreams, filename); goto _fail; } if (ovf_info->channels != 1 && ovf_info->channels != 2) { Con_Printf("Unsupported number of channels %d in %s\n", ovf_info->channels, filename); goto _fail; } stream->info.rate = ovf_info->rate; stream->info.channels = ovf_info->channels; stream->info.width = VORBIS_SAMPLEWIDTH; return stream; _fail: if (res == 0) ov_clear(ovFile); Z_Free(ovFile); S_CodecUtilClose(&stream); return NULL; }
/* ================= S_OGG_CodecOpenStream ================= */ snd_stream_t* S_OGG_CodecOpenStream(const char* filename) { snd_stream_t* stream; // OGG codec control structure OggVorbis_File* vf; // some variables used to get informations about the OGG vorbis_info* OGGInfo; ogg_int64_t numSamples; // check if input is valid if (!filename) { return NULL; } // Open the stream stream = S_CodecUtilOpen(filename, &ogg_codec); if (!stream) { return NULL; } // alloctate the OggVorbis_File vf = Z_Malloc(sizeof(OggVorbis_File)); if (!vf) { S_CodecUtilClose(&stream); return NULL; } // open the codec with our callbacks and stream as the generic pointer if (ov_open_callbacks(stream, vf, NULL, 0, S_OGG_Callbacks) != 0) { Z_Free(vf); S_CodecUtilClose(&stream); return NULL; } // the stream must be seekable if (!ov_seekable(vf)) { ov_clear(vf); Z_Free(vf); S_CodecUtilClose(&stream); return NULL; } // we only support OGGs with one substream if (ov_streams(vf) != 1) { ov_clear(vf); Z_Free(vf); S_CodecUtilClose(&stream); return NULL; } // get the info about channels and rate OGGInfo = ov_info(vf, 0); if (!OGGInfo) { ov_clear(vf); Z_Free(vf); S_CodecUtilClose(&stream); return NULL; } // get the number of sample-frames in the OGG numSamples = ov_pcm_total(vf, 0); // fill in the info-structure in the stream stream->info.rate = OGGInfo->rate; stream->info.width = OGG_SAMPLEWIDTH; stream->info.channels = OGGInfo->channels; stream->info.samples = numSamples; stream->info.size = stream->info.samples * stream->info.channels * stream->info.width; stream->info.dataofs = 0; // We use stream->pos for the file pointer in the compressed ogg file stream->pos = 0; // We use the generic pointer in stream for the OGG codec control structure stream->ptr = vf; return stream; }
static snd_stream_t *S_MP3_CodecOpenStream (const char *filename) { snd_stream_t *stream; long rate = 0; int encoding = 0, channels = 0; mp3_priv_t *priv = NULL; stream = S_CodecUtilOpen(filename, &mp3_codec); if (!stream) return NULL; stream->priv = Z_Malloc(sizeof(mp3_priv_t)); priv = (mp3_priv_t *) stream->priv; priv->handle = mpg123_new(NULL, NULL); if (priv->handle == NULL) { Con_Printf("Unable to allocate mpg123 handle\n"); goto _fail; } priv->handle_newed = 1; if (mpg123_replace_reader_handle(priv->handle, mp3_read, mp3_seek, NULL) != MPG123_OK || mpg123_open_handle(priv->handle, &stream->fh) != MPG123_OK) { Con_Printf("Unable to open mpg123 handle\n"); goto _fail; } priv->handle_opened = 1; if (mpg123_getformat(priv->handle, &rate, &channels, &encoding) != MPG123_OK) { Con_Printf("Unable to retrieve mpg123 format for %s\n", filename); goto _fail; } switch (channels) { case MPG123_MONO: stream->info.channels = 1; break; case MPG123_STEREO: stream->info.channels = 2; break; default: Con_Printf("Unsupported number of channels %d in %s\n", channels, filename); goto _fail; } stream->info.rate = rate; switch (encoding) { case MPG123_ENC_UNSIGNED_8: stream->info.width = 1; break; case MPG123_ENC_SIGNED_8: /* unsupported: force mpg123 to convert */ stream->info.width = 1; encoding = MPG123_ENC_UNSIGNED_8; break; case MPG123_ENC_SIGNED_16: stream->info.width = 2; break; case MPG123_ENC_UNSIGNED_16: default: /* unsupported: force mpg123 to convert */ stream->info.width = 2; encoding = MPG123_ENC_SIGNED_16; break; } if (mpg123_format_support(priv->handle, rate, encoding) == 0) { Con_Printf("Unsupported format for %s\n", filename); goto _fail; } mpg123_format_none(priv->handle); mpg123_format(priv->handle, rate, channels, encoding); return stream; _fail: if (priv) { if (priv->handle_opened) mpg123_close(priv->handle); if (priv->handle_newed) mpg123_delete(priv->handle); Z_Free(stream->priv); } S_CodecUtilClose(&stream); return NULL; }