static bool vorbis_scan_stream(struct input_stream *is, const struct tag_handler *handler, void *handler_ctx) { struct vorbis_input_stream vis; OggVorbis_File vf; if (!vorbis_is_open(&vis, &vf, NULL, is)) return false; tag_handler_invoke_duration(handler, handler_ctx, (int)(ov_time_total(&vf, -1) + 0.5)); vorbis_comments_scan(ov_comment(&vf, -1)->user_comments, handler, handler_ctx); ov_clear(&vf); return true; }
static gboolean vorbis_update_replaygain(OggVorbis_File *vf, ReplayGainInfo *rg_info) { vorbis_comment *comment; gchar *rg_gain, *rg_peak; if (vf == NULL || rg_info == NULL || (comment = ov_comment(vf, -1)) == NULL) { #ifdef DEBUG printf ("No replay gain info.\n"); #endif return FALSE; } rg_gain = vorbis_comment_query(comment, "replaygain_album_gain", 0); if (!rg_gain) rg_gain = vorbis_comment_query(comment, "rg_audiophile", 0); /* Old */ rg_info->album_gain = (rg_gain != NULL) ? atof_no_locale (rg_gain) : 0.0; #ifdef DEBUG printf ("Album gain: %s (%f)\n", rg_gain, rg_info->album_gain); #endif rg_gain = vorbis_comment_query(comment, "replaygain_track_gain", 0); if (!rg_gain) rg_gain = vorbis_comment_query(comment, "rg_radio", 0); /* Old */ rg_info->track_gain = (rg_gain != NULL) ? atof_no_locale (rg_gain) : 0.0; #ifdef DEBUG printf ("Track gain: %s (%f)\n", rg_gain, rg_info->track_gain); #endif rg_peak = vorbis_comment_query(comment, "replaygain_album_peak", 0); rg_info->album_peak = rg_peak != NULL ? atof_no_locale (rg_peak) : 0.0; #ifdef DEBUG printf ("Album peak: %s (%f)\n", rg_peak, rg_info->album_peak); #endif rg_peak = vorbis_comment_query(comment, "replaygain_track_peak", 0); if (!rg_peak) rg_peak = vorbis_comment_query(comment, "rg_peak", 0); /* Old */ rg_info->track_peak = rg_peak != NULL ? atof_no_locale (rg_peak) : 0.0; #ifdef DEBUG printf ("Track peak: %s (%f)\n", rg_peak, rg_info->track_peak); #endif return TRUE; }
int vorbis_source_init(audio_source *src, const char* file) { vorbis_source *local; int ret; // Init local struct local = malloc(sizeof(vorbis_source)); // Try to open up the audio file ret = ov_fopen(file, &local->src_file); if(ret != 0) { PERROR("Vorbis Source: File '%s' could not be opened: ", file, vorbis_text_error(ret)); goto error_1; } // Get file information vorbis_info *vi = ov_info(&local->src_file, -1); char **comment_ptr = ov_comment(&local->src_file, -1)->user_comments; // Audio information source_set_frequency(src, vi->rate); source_set_bytes(src, 2); source_set_channels(src, vi->channels); // Set callbacks source_set_userdata(src, local); source_set_update_cb(src, vorbis_source_update); source_set_close_cb(src, vorbis_source_close); // Some debug info DEBUG("Vorbis Source: Loaded file '%s' succesfully (%d Hz, %d ch).", file, vi->rate, vi->channels); while(*comment_ptr) { DEBUG(" * Comment: %s", *comment_ptr); ++comment_ptr; } // All done return 0; error_1: free(local); return 1; }
void OggStream::open(std::string path) { int result; oggFile = fopen(path.c_str(), "rb"); if (!oggFile) { g_logger->debug_print(WIP_ERROR,"Could not open Ogg file."); return; } result = ov_open(oggFile, &oggStream, NULL, 0); if (result < 0) { fclose(oggFile); std::string out = std::string("Could not open Ogg stream. ") + errorString(result); g_logger->debug_print(WIP_ERROR,(char*)out.c_str()); return; } vorbisInfo = ov_info(&oggStream, -1); vorbisComment = ov_comment(&oggStream, -1); if(vorbisInfo->channels == 1) format = AL_FORMAT_MONO16; else format = AL_FORMAT_STEREO16; alGenBuffers(2, buffers); check(); alGenSources(1, &source); check(); alSource3f(source, AL_POSITION, 0.0, 0.0, 0.0); alSource3f(source, AL_VELOCITY, 0.0, 0.0, 0.0); alSource3f(source, AL_DIRECTION, 0.0, 0.0, 0.0); alSourcef (source, AL_ROLLOFF_FACTOR, 0.0 ); alSourcei (source, AL_SOURCE_RELATIVE, AL_TRUE ); }
static int update_vorbis_comments (DB_playItem_t *it, OggVorbis_File *vorbis_file, const int tracknum) { const vorbis_comment *vc = ov_comment(vorbis_file, tracknum); if (!vc) { trace("update_vorbis_comments: ov_comment failed\n"); return -1; } deadbeef->pl_delete_all_meta (it); for (int i = 0; i < vc->comments; i++) { char *tag = strdup(vc->user_comments[i]); char *value; if (tag && (value = strchr(tag, '='))) { *value++ = '\0'; if (!replaygain_tag(it, DDB_REPLAYGAIN_ALBUMGAIN, tag, value) && !replaygain_tag(it, DDB_REPLAYGAIN_ALBUMPEAK, tag, value) && !replaygain_tag(it, DDB_REPLAYGAIN_TRACKGAIN, tag, value) && !replaygain_tag(it, DDB_REPLAYGAIN_TRACKPEAK, tag, value)) { if (!strcasecmp(tag, gain_tag_name(RG_REFERENCE_LOUDNESS))) deadbeef->pl_replace_meta(it, ":REPLAYGAIN_REFERENCE_LOUDNESS", value); else add_meta(it, oggedit_map_tag(tag, "tag2meta"), value); } free(tag); } } deadbeef->pl_add_meta (it, "title", NULL); uint32_t f = deadbeef->pl_get_item_flags (it); f &= ~DDB_TAG_MASK; f |= DDB_TAG_VORBISCOMMENTS; deadbeef->pl_set_item_flags (it, f); ddb_playlist_t *plt = deadbeef->plt_get_curr (); if (plt) { deadbeef->plt_modified (plt); deadbeef->plt_unref (plt); } deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0); return 0; }
static status_t HandleOGG( const char *filename, MediaScannerClient *client) { int duration; FILE *file = fopen(filename,"r"); if (!file) return UNKNOWN_ERROR; OggVorbis_File vf; if (ov_open(file, &vf, NULL, 0) < 0) { return UNKNOWN_ERROR; } char **ptr=ov_comment(&vf,-1)->user_comments; while(*ptr){ char *val = strstr(*ptr, "="); if (val) { int keylen = val++ - *ptr; char key[keylen + 1]; strncpy(key, *ptr, keylen); key[keylen] = 0; if (!client->addStringTag(key, val)) goto failure; } ++ptr; } // Duration duration = ov_time_total(&vf, -1); if (duration > 0) { char buffer[20]; sprintf(buffer, "%d", duration); if (!client->addStringTag("duration", buffer)) goto failure; } ov_clear(&vf); // this also closes the FILE return OK; failure: ov_clear(&vf); // this also closes the FILE return UNKNOWN_ERROR; }
void vorbis_send_metadata(file_decoder_t * fdec, vorbis_pdata_t * pd) { vorbis_comment * vc = ov_comment(&pd->vf, -1); metadata_t * meta = metadata_from_vorbis_comment(vc); if (fdec->is_stream) { meta->writable = 0; } else { if (access(fdec->filename, R_OK | W_OK) == 0) { meta->writable = 1; fdec->meta_write = vorbis_write_metadata; } else { meta->writable = 0; } } if (fdec->is_stream) { httpc_add_headers_meta(pd->session, meta); } meta->fdec = fdec; fdec->meta = meta; }
static int fill_comments(struct ogg_context *ctx, struct ogg_oggfile *ogg) { OggVorbis_File ovf; vorbis_comment *ovc; char *key, *value; int i; assert(ctx != NULL); assert(ogg != NULL); if (ov_fopen(ogg->filename, &ovf) != 0) { warnx("could not open file: %s", ogg->filename); return (1); } if ((ovc = ov_comment(&ovf, -1)) == NULL) { warnx("could not read comments for file: %s", ogg->filename); return (1); } for (i = 0; i < ovc->comments; i++) { value = ovc->user_comments[i]; key = strsep(&value, "="); if (strcasecmp(key, "artist") == 0) do_iconv(ctx, value, ogg->artist, sizeof(ogg->artist)); else if (strcasecmp(key, "album") == 0) do_iconv(ctx, value, ogg->album, sizeof(ogg->album)); else if (strcasecmp(key, "title") == 0) do_iconv(ctx, value, ogg->title, sizeof(ogg->title)); if (ogg->artist == NULL || ogg->album == NULL || ogg->title == NULL) { warnx("insufficient comments for file: %s", ogg->filename); return (1); } } if (ov_clear(&ovf) != 0) warnx("could not close file: %s", ogg->filename); return (0); }
static Tuple * get_tuple_for_vorbisfile(OggVorbis_File * vorbisfile, const gchar *filename) { Tuple *tuple; gint length; vorbis_comment *comment = NULL; tuple = tuple_new_from_filename(filename); length = vfs_is_streaming (vorbisfile->datasource) ? -1 : ov_time_total (vorbisfile, -1) * 1000; /* associate with tuple */ tuple_set_int(tuple, FIELD_LENGTH, length); if ((comment = ov_comment(vorbisfile, -1)) != NULL) { gchar *tmps; set_tuple_str(tuple, FIELD_TITLE, comment, "title"); set_tuple_str(tuple, FIELD_ARTIST, comment, "artist"); set_tuple_str(tuple, FIELD_ALBUM, comment, "album"); set_tuple_str(tuple, FIELD_GENRE, comment, "genre"); set_tuple_str(tuple, FIELD_COMMENT, comment, "comment"); if ((tmps = vorbis_comment_query(comment, "tracknumber", 0)) != NULL) tuple_set_int(tuple, FIELD_TRACK_NUMBER, atoi(tmps)); if ((tmps = vorbis_comment_query (comment, "date", 0)) != NULL) tuple_set_int (tuple, FIELD_YEAR, atoi (tmps)); } vorbis_info * info = ov_info (vorbisfile, -1); tuple_set_format (tuple, "Ogg Vorbis", info->channels, info->rate, info->bitrate_nominal / 1000); tuple_set_str(tuple, FIELD_MIMETYPE, "application/ogg"); return tuple; }
Sound_Stream_AL::Sound_Stream_AL(const String &path, const bool &looping_, const float &time_) : buffers_used(0), looping(looping_) { if(!dynamic_cast<Sound_Renderer_AL *>(&get_Sound().get_Renderer())) throw Sound_Stream_Init_Failure(); const int result = ov_fopen((path + ".ogg").c_str(), &oggStream); if(result < 0) throw Sound_Stream_Ogg_Read_Failure(); vorbisInfo = ov_info(&oggStream, -1); vorbisComment = ov_comment(&oggStream, -1); if(vorbisInfo->channels == 1) format = AL_FORMAT_MONO16; else format = AL_FORMAT_STEREO16; ov_time_seek(&oggStream, time_); Sound_Renderer_AL::alGenBuffers()(NUM_BUFFERS, buffers); Sound_Renderer_AL::alGenSources()(1, &source); ALfloat pos[3] = {0.0f, 0.0f, 0.0f}; Sound_Renderer_AL::alSourcefv()(source, AL_POSITION, pos ); Sound_Renderer_AL::alSourcefv()(source, AL_VELOCITY, pos ); Sound_Renderer_AL::alSourcefv()(source, AL_DIRECTION, pos ); Sound_Renderer_AL::alSourcef() (source, AL_ROLLOFF_FACTOR, 0.0 ); Sound_Renderer_AL::alSourcei() (source, AL_SOURCE_RELATIVE, AL_TRUE); const ALenum error = Sound_Renderer_AL::alGetError()(); if(error != AL_NO_ERROR) { destroy(); std::cerr << "OpenAL error: " << Sound_Renderer_AL::errorString(error) << std::endl; throw Sound_Stream_Init_Failure(); } }
static void in_vorbis_set_metadata (ices_vorbis_in_t* vorbis_data) { vorbis_comment* comment; char* key; char* artist = NULL; char* title = NULL; int i; if (! (comment = ov_comment (vorbis_data->vf, -1))) return; for (i = 0; i < comment->comments; i++) { key = comment->user_comments[i]; ices_log_debug ("Vorbis comment found: %s", key); if (! strncasecmp ("artist", key, 6)) artist = key+7; else if (! strncasecmp ("title", key, 5)) title = key+6; } ices_metadata_set (artist, title); }
std::string GetOggTitle(std::string file) { OggVorbis_File f; std::string result = ""; if (ov_fopen(file.c_str(), &f) == 0) { vorbis_comment *comment = ov_comment(&f, -1); for (int i = 0; i < comment->comments; i++) { std::string user_comment = comment->user_comments[i]; auto splitvec = Utility::TokenSplit(user_comment, "="); if (splitvec[0] == "TITLE") { result = splitvec[1]; break; } } ov_clear(&f); } return result; }
bool AudioSourceOGG::Open(const char* Filename) { #if !(defined WIN32) || (defined MINGW) int32 retv = ov_fopen(Filename, &mOggFile); #else FILE* fp = _wfopen(Utility::Widen(Filename).c_str(), L"rb"); int retv = -1; if (fp) retv = ov_open_callbacks(static_cast<void*>(fp), &mOggFile, nullptr, 0, fileInterfaceOgg); #endif #ifndef NDEBUG dFILENAME = Filename; #endif #if !(defined WIN32) || (defined MINGW) if (retv == 0) #else if (retv == 0 && fp) #endif { info = ov_info(&mOggFile, -1); comment = ov_comment(&mOggFile, -1); mIsValid = true; mIsDataLeft = true; } else { mIsValid = false; Log::Printf("Failure loading ogg file: %s (%d)\n", Filename, retv); } return mIsValid; }
static gboolean get_song_image (const gchar * filename, VFSFile * file, void * * data, gint64 * size) { OggVorbis_File vfile; if (ov_open_callbacks (file, & vfile, NULL, 0, vfs_is_streaming (file) ? vorbis_callbacks_stream : vorbis_callbacks) < 0) return FALSE; vorbis_comment * comment = ov_comment (& vfile, -1); if (! comment) goto ERR; const gchar * s; if ((s = vorbis_comment_query (comment, "METADATA_BLOCK_PICTURE", 0))) { gsize length2; void * data2 = g_base64_decode (s, & length2); if (! data2 || length2 < 8) goto PARSE_ERR; gint mime_length = GUINT32_FROM_BE (* (guint32 *) (data2 + 4)); if (length2 < 8 + mime_length + 4) goto PARSE_ERR; gint desc_length = GUINT32_FROM_BE (* (guint32 *) (data2 + 8 + mime_length)); if (length2 < 8 + mime_length + 4 + desc_length + 20) goto PARSE_ERR; * size = GUINT32_FROM_BE (* (guint32 *) (data2 + 8 + mime_length + 4 + desc_length + 16)); if (length2 < 8 + mime_length + 4 + desc_length + 20 + * size) goto PARSE_ERR; * data = g_memdup ((char *) data2 + 8 + mime_length + 4 + desc_length + 20, * size); g_free (data2); ov_clear (& vfile); return TRUE; PARSE_ERR: fprintf (stderr, "vorbis: Error parsing METADATA_BLOCK_PICTURE in %s.\n", filename); g_free (data2); } if ((s = vorbis_comment_query (comment, "COVERART", 0))) { gsize length2; void * data2 = g_base64_decode (s, & length2); if (! data2 || ! length2) { fprintf (stderr, "vorbis: Error parsing COVERART in %s.\n", filename); g_free (data2); goto ERR; } * data = data2; * size = length2; ov_clear (& vfile); return TRUE; } ERR: ov_clear (& vfile); return FALSE; }
void VorbisLMC::DecodeWork() { void *pOutBuffer; Error Err; int32 iValue; int32 section, ret; OutputInfo *info; vorbis_info *vi; uint32 bytesCopied, bytesPerFrame; int bitrateLoops = 0; assert(m_pPmi); assert(m_pPmo); m_pSleepSem->Wait(); m_pPmi->Wake(); Err = CanDecode(); if (Err == kError_Interrupt) return; if (Err != kError_NoErr) { m_pContext->log->Error("CanDecode returned false.\n"); if (m_decodeInfo.sendInfo) { ReportStatus(szCannotDecode); m_pTarget->AcceptEvent(new Event(INFO_DoneOutputtingDueToError)); } else ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOErrorEvent()); return; } Err = ExtractMediaInfo(); if (Err == kError_Interrupt) return; if (IsError(Err)) { m_pContext->log->Error("ExtractMediaInfo failed: %d\n", Err); if (m_decodeInfo.sendInfo) { ReportStatus(szCannotDecode); m_pTarget->AcceptEvent(new Event(INFO_DoneOutputtingDueToError)); } else ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOErrorEvent()); return; } if (!m_bInit) { Err = InitDecoder(); if (Err == kError_Interrupt) return; if (IsError(Err)) { m_pContext->log->Error("Initializing the decoder failed: %d\n", Err); ReportError("Initializing the decoder failed."); return; } } m_pContext->prefs->GetPrefInt32(kDecoderThreadPriorityPref, &iValue); m_decoderThread->SetPriority(iValue); bytesCopied = 0; bytesPerFrame = 1; for (m_frameCounter = 0; !m_bExit;) { if (m_bPause) { m_pPauseSem->Wait(); if (m_bExit) break; } if (m_newPos >= 0) { ov_time_seek(&m_vf, (double)(m_newPos / iFramesPerSecond)); m_frameCounter = m_newPos - 1; m_newPos = -1; bytesCopied = bytesPerFrame; } if (bytesCopied >= bytesPerFrame) { m_frameCounter += bytesCopied / bytesPerFrame; bytesCopied %= bytesPerFrame; ((EventBuffer *)m_pOutputBuffer)->AcceptEvent( new PMOTimeInfoEvent(m_frameCounter)); bitrateLoops++; if (bitrateLoops == iBitrateLoopsPerUpdate && m_decodeInfo.sendInfo) { int b; b = ov_bitrate_instant(&m_vf), vi = ov_info(&m_vf, -1); VorbisInfoEvent *mie = new VorbisInfoEvent(b, vi->channels, vi->rate, 1. / (float)iFramesPerSecond); m_pTarget->AcceptEvent(mie); bitrateLoops = 0; } } Err = m_pOutputBuffer->BeginWrite(pOutBuffer, iDecodeBlockSize); if (Err == kError_Interrupt) { break; } if (Err == kError_BufferTooSmall) { if (Sleep()) break; continue; } if (Err != kError_NoErr) { ReportError(szFailWrite); m_pContext->log->Error("LMC: Cannot write to eventbuffer: %s (%d)\n", m_szError, Err); break; } section = -1; ret = ov_read(&m_vf, (char *)pOutBuffer, iDecodeBlockSize, 0, 2, 1, §ion); if (ret == 0) { m_pOutputBuffer->EndWrite(0); break; } if (section != m_section) { vi = ov_info(&m_vf, -1); info = new OutputInfo; info->bits_per_sample = 16; info->number_of_channels = m_channels = vi->channels; info->samples_per_second = m_rate = vi->rate; info->samples_per_frame = vi->rate / iFramesPerSecond; info->max_buffer_size = 16384; m_frameCounter = 0; bytesCopied = 0; bytesPerFrame = (vi->rate / iFramesPerSecond) * sizeof(ogg_int16_t) * vi->channels; m_section = section; m_pOutputBuffer->EndWrite(0); ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOInitEvent(info)); ((EventBuffer *)m_pOutputBuffer)->AcceptEvent( new PMOTimeInfoEvent(m_frameCounter)); Err = m_pOutputBuffer->BeginWrite(pOutBuffer, iDecodeBlockSize); if (Err != kError_NoErr) { assert(0); } vorbis_comment *comment; comment = ov_comment(&m_vf, -1); if (comment) { PlaylistItem *plItem = m_pContext->plm->GetCurrentItem(); if (plItem) { MetaData mdata = plItem->GetMetaData(); string iso; char *temp; temp = vorbis_comment_query(comment, "title", 0); if (temp) { iso = ConvertToISO(temp); mdata.SetTitle(iso); } temp = vorbis_comment_query(comment, "artist", 0); if (temp) { iso = ConvertToISO(temp); mdata.SetArtist(iso); } temp = vorbis_comment_query(comment, "album", 0); if (temp) { iso = ConvertToISO(temp); mdata.SetAlbum(iso); } temp = vorbis_comment_query(comment, "tracknumber", 0); if (temp) mdata.SetTrack(atoi(temp)); plItem->SetMetaData(&mdata); m_pContext->target->AcceptEvent( new PlaylistCurrentItemInfoEvent(plItem, m_pContext->plm)); } } } if(ret <0) ret=0; // hole/error in data - we can safely ignore this m_pOutputBuffer->EndWrite(ret); bytesCopied += ret; } ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOQuitEvent()); ov_clear(&m_vf); return; }
/* Load an OGG stream from an SDL_RWops object */ OGG_music *OGG_new_RW(SDL_RWops *src, int freesrc) { OGG_music *music; ov_callbacks callbacks; if(!Mix_Init(MIX_INIT_OGG)) return(NULL); SDL_memset(&callbacks, 0, sizeof(callbacks)); callbacks.read_func = sdl_read_func; callbacks.seek_func = sdl_seek_func; callbacks.tell_func = sdl_tell_func; music = (OGG_music *)SDL_malloc(sizeof * music); if(music) { vorbis_info *vi; vorbis_comment *ptr; int isLength = 0; int i; ogg_int64_t total; /* Initialize the music structure */ SDL_memset(music, 0, (sizeof * music)); music->src = src; music->freesrc = freesrc; OGG_stop(music); OGG_setvolume(music, MIX_MAX_VOLUME); music->section = -1; music->channels = 0; music->mus_title = NULL; music->mus_artist = NULL; music->mus_album = NULL; music->mus_copyright = NULL; MyResample_zero(&music->resample); music->loop = -1; music->loop_start = -1; music->loop_end = 0; music->loop_len = 0; if(vorbis.ov_open_callbacks(src, &music->vf, NULL, 0, callbacks) < 0) { SDL_SetError("Not an Ogg Vorbis audio stream"); SDL_free(music); return(NULL); } vi = vorbis.ov_info(&music->vf, -1); music->channels = vi->channels; /* Parse comments and extract title and loop points */ ptr = ov_comment(&music->vf, -1); for(i = 0; i < ptr->comments; i++) { int paramLen = ptr->comment_lengths[i] + 1; char *param = (char *)SDL_malloc(paramLen); char *argument = param; char *value = param; memset(param, 0, paramLen); memcpy(param, ptr->user_comments[i], ptr->comment_lengths[i]); value = strchr(param, '='); if(value == NULL) { value = param + paramLen - 1; /* set null */ } else { *(value++) = '\0'; } #ifdef __USE_ISOC99 #define A_TO_OGG64(x) (ogg_int64_t)atoll(x) #else #define A_TO_OGG64(x) (ogg_int64_t)atol(x) #endif if(strcasecmp(argument, "LOOPSTART") == 0) music->loop_start = A_TO_OGG64(value); else if(strcasecmp(argument, "LOOPLENGTH") == 0) { music->loop_len = A_TO_OGG64(value); isLength = 1; } else if(strcasecmp(argument, "LOOPEND") == 0) { isLength = 0; music->loop_end = A_TO_OGG64(value); } else if(strcasecmp(argument, "TITLE") == 0) { music->mus_title = (char *)SDL_malloc(sizeof(char) * strlen(value) + 1); strcpy(music->mus_title, value); } else if(strcasecmp(argument, "ARTIST") == 0) { music->mus_artist = (char *)SDL_malloc(sizeof(char) * strlen(value) + 1); strcpy(music->mus_artist, value); } else if(strcasecmp(argument, "ALBUM") == 0) { music->mus_album = (char *)SDL_malloc(sizeof(char) * strlen(value) + 1); strcpy(music->mus_album, value); } else if(strcasecmp(argument, "COPYRIGHT") == 0) { music->mus_copyright = (char *)SDL_malloc(sizeof(char) * strlen(value) + 1); strcpy(music->mus_copyright, value); } SDL_free(param); } #undef A_TO_OGG64 if(isLength == 1) music->loop_end = music->loop_start + music->loop_len; else music->loop_len = music->loop_end - music->loop_start; total = ov_pcm_total(&music->vf, -1); if(((music->loop_start >= 0) || (music->loop_end > 0)) && ((music->loop_start < music->loop_end) || (music->loop_end == 0)) && (music->loop_start < total) && (music->loop_end <= total)) { if(music->loop_start < 0) music->loop_start = 0; if(music->loop_end == 0) music->loop_end = total; music->loop = 1; music->loop_len_ch = music->channels; } } else { SDL_OutOfMemory(); return(NULL); } return (music); }
static gboolean vorbis_play (const gchar * filename, VFSFile * file) { if (file == NULL) return FALSE; vorbis_info *vi; OggVorbis_File vf; gint last_section = -1; ReplayGainInfo rg_info; gfloat pcmout[PCM_BUFSIZE*sizeof(float)], **pcm; gint bytes, channels, samplerate, br; gchar * title = NULL; memset(&vf, 0, sizeof(vf)); gboolean error = FALSE; if (ov_open_callbacks (file, & vf, NULL, 0, vfs_is_streaming (file) ? vorbis_callbacks_stream : vorbis_callbacks) < 0) { error = TRUE; goto play_cleanup; } vi = ov_info(&vf, -1); if (vi->channels > 2) goto play_cleanup; br = vi->bitrate_nominal; channels = vi->channels; samplerate = vi->rate; aud_input_set_bitrate (br); if (!aud_input_open_audio(FMT_FLOAT, samplerate, channels)) { error = TRUE; goto play_cleanup; } vorbis_update_replaygain(&vf, &rg_info); aud_input_set_gain (& rg_info); /* * Note that chaining changes things here; A vorbis file may * be a mix of different channels, bitrates and sample rates. * You can fetch the information for any section of the file * using the ov_ interface. */ while (! aud_input_check_stop ()) { int seek_value = aud_input_check_seek(); if (seek_value >= 0 && ov_time_seek (& vf, (double) seek_value / 1000) < 0) { fprintf (stderr, "vorbis: seek failed\n"); error = TRUE; break; } gint current_section = last_section; bytes = ov_read_float(&vf, &pcm, PCM_FRAMES, ¤t_section); if (bytes == OV_HOLE) continue; if (bytes <= 0) break; bytes = vorbis_interleave_buffer (pcm, bytes, channels, pcmout); { /* try to detect when metadata has changed */ vorbis_comment * comment = ov_comment (& vf, -1); const gchar * new_title = (comment == NULL) ? NULL : vorbis_comment_query (comment, "title", 0); if (new_title != NULL && (title == NULL || strcmp (title, new_title))) { g_free (title); title = g_strdup (new_title); aud_input_set_tuple (get_tuple_for_vorbisfile (& vf, filename)); } } if (current_section != last_section) { /* * The info struct is different in each section. vf * holds them all for the given bitstream. This * requests the current one */ vi = ov_info(&vf, -1); if (vi->channels > 2) goto stop_processing; if (vi->rate != samplerate || vi->channels != channels) { samplerate = vi->rate; channels = vi->channels; if (!aud_input_open_audio(FMT_FLOAT, vi->rate, vi->channels)) { error = TRUE; goto stop_processing; } vorbis_update_replaygain(&vf, &rg_info); aud_input_set_gain (& rg_info); /* audio reopened */ } } aud_input_write_audio (pcmout, bytes); stop_processing: if (current_section != last_section) { aud_input_set_bitrate (br); last_section = current_section; } } /* main loop */ play_cleanup: ov_clear(&vf); g_free (title); return ! error; }
/* public */ static void vorbis_stream_decode(struct decoder *decoder, struct input_stream *input_stream) { GError *error = NULL; OggVorbis_File vf; struct vorbis_input_stream vis; struct audio_format audio_format; float total_time; int current_section; int prev_section = -1; long ret; char chunk[OGG_CHUNK_SIZE]; long bitRate = 0; long test; const vorbis_info *vi; enum decoder_command cmd = DECODE_COMMAND_NONE; if (ogg_stream_type_detect(input_stream) != VORBIS) return; /* rewind the stream, because ogg_stream_type_detect() has moved it */ input_stream_lock_seek(input_stream, 0, SEEK_SET, NULL); if (!vorbis_is_open(&vis, &vf, decoder, input_stream)) return; vi = ov_info(&vf, -1); if (vi == NULL) { g_warning("ov_info() has failed"); return; } if (!audio_format_init_checked(&audio_format, vi->rate, SAMPLE_FORMAT_S16, vi->channels, &error)) { g_warning("%s", error->message); g_error_free(error); return; } total_time = ov_time_total(&vf, -1); if (total_time < 0) total_time = 0; decoder_initialized(decoder, &audio_format, vis.seekable, total_time); do { if (cmd == DECODE_COMMAND_SEEK) { double seek_where = decoder_seek_where(decoder); if (0 == ov_time_seek_page(&vf, seek_where)) { decoder_command_finished(decoder); } else decoder_seek_error(decoder); } ret = ov_read(&vf, chunk, sizeof(chunk), OGG_DECODE_USE_BIGENDIAN, 2, 1, ¤t_section); if (ret == OV_HOLE) /* bad packet */ ret = 0; else if (ret <= 0) /* break on EOF or other error */ break; if (current_section != prev_section) { char **comments; vi = ov_info(&vf, -1); if (vi == NULL) { g_warning("ov_info() has failed"); break; } if (vi->rate != (long)audio_format.sample_rate || vi->channels != (int)audio_format.channels) { /* we don't support audio format change yet */ g_warning("audio format change, stopping here"); break; } comments = ov_comment(&vf, -1)->user_comments; vorbis_send_comments(decoder, input_stream, comments); struct replay_gain_info rgi; if (vorbis_comments_to_replay_gain(&rgi, comments)) decoder_replay_gain(decoder, &rgi); prev_section = current_section; } if ((test = ov_bitrate_instant(&vf)) > 0) bitRate = test / 1000; cmd = decoder_data(decoder, input_stream, chunk, ret, bitRate); } while (cmd != DECODE_COMMAND_STOP); ov_clear(&vf); }
ULONG _System decoder_fileinfo(char *pszFilename, DECODER_INFO *pInfo) { if(pInfo == NULL) { return 200; } { HFILE stream; ULONG rc; OggVorbis_File vf; vorbis_info *vi = NULL; ov_callbacks callbacks = {read_func, seek_func, close_func, tell_func}; if (pszFilename != NULL && pszFilename[0] != 0) { ULONG ulAction; rc = DosOpen( pszFilename, &stream, &ulAction, 0, FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS, OPEN_ACCESS_READONLY | OPEN_SHARE_DENYWRITE, 0 ); if (rc != 0) { return 100; } // The ov_open() function performs full stream detection and machine // initialization. If it returns 0, the stream *is* Vorbis and we're // fully ready to decode. if (ov_open_callbacks( (void *)stream, &vf, NULL, 0, callbacks) < 0) { DosClose( stream ); return 200; } /* 曲の時間(ms) */ pInfo->songlength = (int)(ov_time_total(&vf, -1) * 1000.0); vi = ov_info( &vf, -1); pInfo->mpeg = 0; pInfo->layer = 0; pInfo->numchannels = 2; /* 曲データの始まるファイル先頭からの位置(byte) */ /* 多分、MAC Binary用かな? */ pInfo->junklength = 0; #if 1 { vorbis_comment *comment; comment = ov_comment( &vf, -1 ); if(comment) { char *title, *artist; pInfo->bitrate = ov_bitrate( &vf, -1 ); sprintf( pInfo->tech_info, "%5.1fkbs, %4.1fkHz, %s", (float)pInfo->bitrate / 1000.0, (float)vi->rate / 1000.0, (vi->channels == 1) ? "Mono" : "Stereo" ); title = vorbis_comment_query( comment, "title", 0 ); if(title) strncpy( pInfo->title, title, 128 ); artist = vorbis_comment_query( comment, "artist", 0 ); if(artist) strncpy( pInfo->artist, artist, 128 ); // strcpy( pInfo->album, "album" ); // strcpy( pInfo->year, "year" ); // strcpy( pInfo->comment, "comment" ); // strcpy( pInfo->genre, "genre" ); } } #endif #if 0 /* general technical information string */ char tech_info[128]; /* song information */ char title[128]; char artist[128]; char album[128]; char year[128]; char comment[128]; char genre[128]; #endif pInfo->format.size = sizeof(FORMAT_INFO); pInfo->format.samplerate = vi->rate; pInfo->format.channels = vi->channels; pInfo->format.bits = 16; pInfo->bitrate = ov_bitrate( &vf, -1 ) / 1000; pInfo->format.format = WAVE_FORMAT_PCM; if(vi->channels > 2) /* We can't handle this */ { ov_clear( &vf ); DosClose( stream ); return 200; } // once the ov_open() succeeds, the file belongs to vorbisfile. // ov_clear() will close it. ov_clear(&vf); DosClose( stream ); } else { return 200; } } return 0; }
int Audio::loadOggStream(Path path){ int result; AudioSource* source=new AudioSource; source->type=AUDIO_OGG; source->filename=path; source->stream=true; ALenum error=alGetError(); if(!(source->oggFile = fopen(path.getAbsolute().c_str(), "rb"))){ console().write("Could not open Ogg file."); return -1; } if((result = ov_open(source->oggFile, &source->oggStream, NULL, 0)) < 0) { fclose(source->oggFile); console().write("Could not open Ogg stream. " + errorString(result)); return -1; } source->vorbisInfo = ov_info(&source->oggStream, -1); source->vorbisComment = ov_comment(&source->oggStream, -1); source->freq = source->vorbisInfo->rate; if(source->vorbisInfo->channels == 1){ source->format = AL_FORMAT_MONO16; source->stereo=false; }else{ source->format = AL_FORMAT_STEREO16; source->stereo=true; } source->lengthSeconds=ov_time_total(&source->oggStream,-1); error=alGetError(); alGenBuffers(2, source->buffers); alGenSources(1, &source->source); error=alGetError(); if(error==AL_OUT_OF_MEMORY || error==AL_INVALID_VALUE){ //there's not more resources for sources source->alSourceSet=false; }else if(error!=AL_NO_ERROR){ return -1; }else{ source->alSourceSet=true; alSources.pushBack(source->source); source->sourceIndex=sources.size()-1; alSourcePriority.pushBack(0); while(alSourceUsedBy.size()<=sources.size()){ //note, we haven't actually added this source to the sources list yet, thus the weird index alSourceUsedBy.pushBack(); } alSourceUsedBy[alSources.size()-1]=sources.size(); source->alSourceIndex=alSources.size()-1; } error=alGetError(); if(error == AL_NO_ERROR){ sources.pushBack(source); source->sourceIndex=sources.size()-1; return sources.size()-1; }else{ logs().audio.write("[AudioObject] Error 2 loading file:"+source->filename.getRelative()); console().write(String("audio wav error: error '")+String(alGetString(error))+"' loading file '"+source->filename.getRelative()+"'"); return -1; } }
int Audio::loadOgg(Path path){ engineTime.skipNextFrame(); ALenum errori=alGetError(); AudioSource* source=new AudioSource; source->filename=path; source->type=AUDIO_OGG; int result; if(!(source->oggFile = fopen(path.getAbsolute().c_str(), "rb"))){ console().write("audio error: i/o error, could not open off file '"+path.getRelative()+"'"); return -1; } if((result = ov_open(source->oggFile, &source->oggStream, NULL, 0)) < 0){ fclose(source->oggFile); console().write("audio error: could not open ogg stream '"+path.getRelative()+"'"); return -1; } source->vorbisInfo = ov_info(&source->oggStream, -1); source->vorbisComment = ov_comment(&source->oggStream, -1); if(source->vorbisInfo->channels == 1){ source->format = AL_FORMAT_MONO16; source->stereo=false; }else{ source->format = AL_FORMAT_STEREO16; source->stereo=true; } source->freq = source->vorbisInfo->rate; alGenBuffers(1, &source->buffer); errori=alGetError(); if(errori != AL_NO_ERROR){ logs().audio.write("[AudioObject] error '"+String(alGetString(errori))+"' loading file '"+path.getRelative()+"'"); console().write(String("audio ogg error: error '"+String(alGetString(errori))+"' loading file '"+path.getRelative()+"'")); return -1; } alGenSources(1, &source->source); errori=alGetError(); if(errori==AL_OUT_OF_MEMORY || errori==AL_INVALID_VALUE){ //there's not more resources for sources source->alSourceSet=false; }else if(errori!=AL_NO_ERROR){ return -1; }else{ source->alSourceSet=true; alSources.pushBack(source->source); source->sourceIndex=sources.size()-1; alSourcePriority.pushBack(0); while(alSourceUsedBy.size()<=sources.size()){ //note, we haven't actually added this source to the sources list yet, thus the weird index alSourceUsedBy.pushBack(); } alSourceUsedBy[alSources.size()-1]=sources.size(); source->alSourceIndex=alSources.size()-1; } if(!source->stream){ std::vector < char > bufferData; #ifdef _WIN32 int endian = 0; // 0 for Little-Endian, 1 for Big-Endian #else #ifdef __LITTLE_ENDIAN__ int endian=0; #else int endian=1; #endif #endif int bitStream; long bytes; char arr[BUFFER_SIZE]; // Local fixed size array do { // Read up to a buffer's worth of decoded sound data bytes = ov_read(&source->oggStream, arr, BUFFER_SIZE, endian, 2, 1, &bitStream); // Append to end of buffer bufferData.insert(bufferData.end(), arr, arr + bytes); } while (bytes > 0); alBufferData(source->buffer, source->format, &bufferData[0], static_cast < ALsizei > (bufferData.size()), source->freq); if(source->alSourceSet){ alSourcei (source->source,AL_BUFFER, source->buffer ); } } ALenum error=alGetError(); if(error == AL_NO_ERROR){ sources.pushBack(source); source->sourceIndex=sources.size()-1; return sources.size()-1; }else{ logs().audio.write("[AudioObject] error 1 '"+String(alGetString(error))+"' loading file '"+path.getRelative()+"'"); console().write(String("audio ogg error: error 1 '"+String(alGetString(error))+"' loading file '"+path.getRelative()+"'")); return -1; } }
int OpenAL::snd_load_file(const char * file, ALuint buffer){ FILE* oggFile; OggVorbis_File oggStream; vorbis_info* vorbisInfo; vorbis_comment* vorbisComment; ALenum format; int result; if(!(oggFile = fopen(file, "rb"))) printf("Could not open Ogg file: %s\n", file); if((result = ov_open(oggFile, &oggStream, NULL, 0)) < 0) { fclose(oggFile); printf("Could not open Ogg stream.\n"); return 1; } vorbisInfo = ov_info(&oggStream, -1); vorbisComment = ov_comment(&oggStream, -1); if(vorbisInfo->channels == 1) format = AL_FORMAT_MONO16; else format = AL_FORMAT_STEREO16; char * dyn_data = NULL; int size = 0; int section; result = 1; printf("Loading sound file %s\n", file); while(result > 0){ char data[BUFFER_SIZE]; result = ov_read(&oggStream, data, BUFFER_SIZE, 0, 2, 1, & section); if(result > 0){ char * tmp; size += result; tmp = (char*)malloc(sizeof(char)*(size)); if(dyn_data != NULL){ memcpy(tmp, dyn_data, sizeof(char)*(size-result)); free(dyn_data); } dyn_data = tmp; tmp += size-result; memcpy(tmp, data, result); } else if(result < 0){ switch(result){ case OV_HOLE: printf("Interruption in the data.%d\n", result); printf("one of: garbage between pages, loss of sync followed by recapture, or a corrupt page\n"); break; case OV_EBADLINK: printf("an invalid stream section was supplied to libvorbisfile, or the requested link is corrupt.\n"); break; case OV_EINVAL: printf("the initial file headers can't be read or are corrupt, or the initial open call for vf failed.\n"); break; } } else if(size == 0){ printf("Date not read.\n"); } } alBufferData(buffer, format, dyn_data, size, vorbisInfo->rate); free(dyn_data); ov_clear(&oggStream); return 0; }
void vorbis_file_info_box(char *fn) { char *track_name, *performer, *album_name, *date, *track_number; char *genre, *user_comment, *tmp; char *description, *version, *isrc, *copyright, *organization; char *location, *vendor = "N/A"; char *rg_track_gain, *rg_album_gain, *rg_track_peak, *rg_album_peak; int time, minutes, seconds, bitrate, avgbitrate, rate, channels; int filesize, i; OggVorbis_File vf; vorbis_info *vi; vorbis_comment *comment = NULL; FILE *fh; gboolean clear_vf = FALSE; g_free(vte.filename); vte.filename = g_strdup(fn); if (!window) { GtkWidget *info_frame, *info_box; GtkWidget *hbox, *label, *filename_hbox, *vbox, *left_vbox; GtkWidget *table, *bbox, *cancel_button; GtkWidget *save_button, *remove_button; window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE); gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &window); gtk_signal_connect(GTK_OBJECT(window), "key_press_event", keypress_cb, NULL); gtk_container_set_border_width(GTK_CONTAINER(window), 10); vbox = gtk_vbox_new(FALSE, 10); gtk_container_add(GTK_CONTAINER(window), vbox); filename_hbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), filename_hbox, FALSE, TRUE, 0); label = gtk_label_new(_("Filename:")); gtk_box_pack_start(GTK_BOX(filename_hbox), label, FALSE, TRUE, 0); filename_entry = gtk_entry_new(); gtk_editable_set_editable(GTK_EDITABLE(filename_entry), FALSE); gtk_box_pack_start(GTK_BOX(filename_hbox), filename_entry, TRUE, TRUE, 0); hbox = gtk_hbox_new(FALSE, 10); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0); left_vbox = gtk_vbox_new(FALSE, 10); gtk_box_pack_start(GTK_BOX(hbox), left_vbox, FALSE, FALSE, 0); tag_frame = gtk_frame_new(_("Ogg Vorbis Tag:")); gtk_box_pack_start(GTK_BOX(left_vbox), tag_frame, FALSE, FALSE, 0); table = gtk_table_new(5, 5, FALSE); gtk_container_set_border_width(GTK_CONTAINER(table), 5); gtk_container_add(GTK_CONTAINER(tag_frame), table); label = gtk_label_new(_("Title:")); gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 5, 5); title_entry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), title_entry, 1, 4, 0, 1, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); label = gtk_label_new(_("Artist:")); gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 5, 5); performer_entry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), performer_entry, 1, 4, 1, 2, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); label = gtk_label_new(_("Album:")); gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 5, 5); album_entry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), album_entry, 1, 4, 2, 3, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); label = gtk_label_new(_("Comment:")); gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, GTK_FILL, GTK_FILL, 5, 5); user_comment_entry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), user_comment_entry, 1, 4, 3, 4, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); label = gtk_label_new(_("Date:")); gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5, GTK_FILL, GTK_FILL, 5, 5); date_entry = gtk_entry_new(); gtk_widget_set_usize(date_entry, 60, -1); gtk_table_attach(GTK_TABLE(table), date_entry, 1, 2, 4, 5, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); label = gtk_label_new(_("Track number:")); gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); gtk_table_attach(GTK_TABLE(table), label, 2, 3, 4, 5, GTK_FILL, GTK_FILL, 5, 5); tracknumber_entry = gtk_entry_new_with_max_length(4); gtk_widget_set_usize(tracknumber_entry, 20, -1); gtk_table_attach(GTK_TABLE(table), tracknumber_entry, 3, 4, 4, 5, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); label = gtk_label_new(_("Genre:")); gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 5, 6, GTK_FILL, GTK_FILL, 5, 5); genre_combo = gtk_combo_new(); if (!genre_list) { for (i = 0; i < sizeof(vorbis_genres)/sizeof(*vorbis_genres) ; i++) genre_list = g_list_prepend(genre_list, _(vorbis_genres[i])); genre_list = g_list_sort(genre_list, (GCompareFunc)g_strcasecmp); } gtk_combo_set_popdown_strings(GTK_COMBO(genre_combo), genre_list); gtk_table_attach(GTK_TABLE(table), genre_combo, 1, 4, 5, 6, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); #ifdef ALL_VORBIS_TAGS label = gtk_label_new(_("Description:")); gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 6, 7, GTK_FILL, GTK_FILL, 5, 5); description_entry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), description_entry, 1, 4, 6, 7, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); label = gtk_label_new(_("Location:")); gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 7, 8, GTK_FILL, GTK_FILL, 5, 5); location_entry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), location_entry, 1, 4, 7, 8, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); label = gtk_label_new(_("Version:")); gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 8, 9, GTK_FILL, GTK_FILL, 5, 5); version_entry = gtk_entry_new(); gtk_widget_set_usize(version_entry, 60, -1); gtk_table_attach(GTK_TABLE(table), version_entry, 1, 2, 8, 9, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); label = gtk_label_new(_("ISRC number:")); gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); gtk_table_attach(GTK_TABLE(table), label, 2, 3, 8, 9, GTK_FILL, GTK_FILL, 5, 5); isrc_entry = gtk_entry_new(); gtk_widget_set_usize(isrc_entry, 20, -1); gtk_table_attach(GTK_TABLE(table), isrc_entry, 3, 4, 8, 9, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); label = gtk_label_new(_("Organization:")); gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 9, 10, GTK_FILL, GTK_FILL, 5, 5); organization_entry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), organization_entry, 1, 4, 9, 10, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); label = gtk_label_new(_("Copyright:")); gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 10, 11, GTK_FILL, GTK_FILL, 5, 5); copyright_entry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), copyright_entry, 1, 4, 10, 11, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); #endif rg_show_button = gtk_check_button_new_with_label(_("ReplayGain Settings:")); gtk_signal_connect(GTK_OBJECT(rg_show_button), "toggled", GTK_SIGNAL_FUNC(rg_show_cb), NULL); gtk_table_attach(GTK_TABLE(table), rg_show_button, 0, 2, 11, 12, GTK_FILL, GTK_FILL, 5, 5); rg_track_label = gtk_label_new(_("Track gain:")); gtk_misc_set_alignment(GTK_MISC(rg_track_label), 1, 0.5); gtk_table_attach(GTK_TABLE(table), rg_track_label, 2, 3, 11, 12, GTK_FILL, GTK_FILL, 5, 5); rg_track_entry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), rg_track_entry, 3, 4, 11, 12, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); rg_track_peak_label = gtk_label_new(_("Track peak:")); gtk_misc_set_alignment(GTK_MISC(rg_track_peak_label), 1, 0.5); gtk_table_attach(GTK_TABLE(table), rg_track_peak_label, 2, 3, 12, 13, GTK_FILL, GTK_FILL, 5, 5); rg_track_peak_entry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), rg_track_peak_entry, 3, 4, 12, 13, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); rg_album_label = gtk_label_new(_("Album gain:")); gtk_misc_set_alignment(GTK_MISC(rg_album_label), 1, 0.5); gtk_table_attach(GTK_TABLE(table), rg_album_label, 2, 3, 13, 14, GTK_FILL, GTK_FILL, 5, 5); rg_album_entry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), rg_album_entry, 3, 4, 13, 14, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); rg_album_peak_label = gtk_label_new(_("Album peak:")); gtk_misc_set_alignment(GTK_MISC(rg_album_peak_label), 1, 0.5); gtk_table_attach(GTK_TABLE(table), rg_album_peak_label, 2, 3, 14, 15, GTK_FILL, GTK_FILL, 5, 5); rg_album_peak_entry = gtk_entry_new(); gtk_table_attach(GTK_TABLE(table), rg_album_peak_entry, 3, 4, 14, 15, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5); bbox = gtk_hbutton_box_new(); gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5); gtk_box_pack_start(GTK_BOX(left_vbox), bbox, FALSE, FALSE, 0); save_button = gtk_button_new_with_label(_("Save")); gtk_signal_connect(GTK_OBJECT(save_button), "clicked", GTK_SIGNAL_FUNC(save_cb), NULL); GTK_WIDGET_SET_FLAGS(save_button, GTK_CAN_DEFAULT); gtk_box_pack_start(GTK_BOX(bbox), save_button, TRUE, TRUE, 0); gtk_widget_grab_default(save_button); remove_button = gtk_button_new_with_label(_("Remove Tag")); gtk_signal_connect_object(GTK_OBJECT(remove_button), "clicked", GTK_SIGNAL_FUNC(remove_cb), NULL); GTK_WIDGET_SET_FLAGS(remove_button, GTK_CAN_DEFAULT); gtk_box_pack_start(GTK_BOX(bbox),remove_button, TRUE, TRUE, 0); cancel_button = gtk_button_new_with_label(_("Cancel")); gtk_signal_connect_object(GTK_OBJECT(cancel_button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(window)); GTK_WIDGET_SET_FLAGS(cancel_button, GTK_CAN_DEFAULT); gtk_box_pack_start(GTK_BOX(bbox),cancel_button, TRUE, TRUE, 0); info_frame = gtk_frame_new(_("Ogg Vorbis Info:")); gtk_box_pack_start(GTK_BOX(hbox), info_frame, FALSE, FALSE, 0); info_box = gtk_vbox_new(FALSE, 5); gtk_container_add(GTK_CONTAINER(info_frame), info_box); gtk_container_set_border_width(GTK_CONTAINER(info_box), 10); gtk_box_set_spacing(GTK_BOX(info_box), 0); bitrate_label = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(bitrate_label), 0, 0); gtk_label_set_justify(GTK_LABEL(bitrate_label), GTK_JUSTIFY_LEFT); gtk_box_pack_start(GTK_BOX(info_box), bitrate_label, FALSE, FALSE, 0); avgbitrate_label = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(avgbitrate_label), 0, 0); gtk_label_set_justify(GTK_LABEL(avgbitrate_label), GTK_JUSTIFY_LEFT); gtk_box_pack_start(GTK_BOX(info_box), avgbitrate_label, FALSE, FALSE, 0); rate_label = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(rate_label), 0, 0); gtk_label_set_justify(GTK_LABEL(rate_label), GTK_JUSTIFY_LEFT); gtk_box_pack_start(GTK_BOX(info_box), rate_label, FALSE, FALSE, 0); channel_label = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(channel_label), 0, 0); gtk_label_set_justify(GTK_LABEL(channel_label), GTK_JUSTIFY_LEFT); gtk_box_pack_start(GTK_BOX(info_box), channel_label, FALSE, FALSE, 0); length_label = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(length_label), 0, 0); gtk_label_set_justify(GTK_LABEL(length_label), GTK_JUSTIFY_LEFT); gtk_box_pack_start(GTK_BOX(info_box), length_label, FALSE, FALSE, 0); filesize_label = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(filesize_label), 0, 0); gtk_label_set_justify(GTK_LABEL(filesize_label), GTK_JUSTIFY_LEFT); gtk_box_pack_start(GTK_BOX(info_box), filesize_label, FALSE, FALSE, 0); vendor_label = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(vendor_label), 0, 0); gtk_label_set_justify(GTK_LABEL(vendor_label), GTK_JUSTIFY_LEFT); gtk_box_pack_start(GTK_BOX(info_box), vendor_label, FALSE, FALSE, 0); replaygain_label = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(replaygain_label), 0, 0); gtk_label_set_justify(GTK_LABEL(replaygain_label), GTK_JUSTIFY_LEFT); gtk_box_pack_start(GTK_BOX(info_box), replaygain_label, FALSE, FALSE, 0); audiophilegain_label = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(audiophilegain_label), 0, 0); gtk_label_set_justify(GTK_LABEL(audiophilegain_label), GTK_JUSTIFY_LEFT); gtk_box_pack_start(GTK_BOX(info_box), audiophilegain_label, FALSE, FALSE, 0); peak_label = gtk_label_new(""); gtk_misc_set_alignment(GTK_MISC(peak_label), 0, 0); gtk_label_set_justify(GTK_LABEL(peak_label), GTK_JUSTIFY_LEFT); gtk_box_pack_start(GTK_BOX(info_box), peak_label, FALSE, FALSE, 0); gtk_widget_show_all(window); } else gdk_window_raise(window->window); if (!g_strncasecmp(vte.filename, "http://", 7)) gtk_widget_set_sensitive(tag_frame, FALSE); else gtk_widget_set_sensitive(tag_frame, TRUE); gtk_label_set_text(GTK_LABEL(bitrate_label), ""); gtk_label_set_text(GTK_LABEL(avgbitrate_label), ""); gtk_label_set_text(GTK_LABEL(rate_label), ""); gtk_label_set_text(GTK_LABEL(channel_label), ""); gtk_label_set_text(GTK_LABEL(length_label), ""); gtk_label_set_text(GTK_LABEL(filesize_label), ""); gtk_label_set_text(GTK_LABEL(vendor_label), ""); if ((fh = fopen(vte.filename, "r")) != NULL) { pthread_mutex_lock(&vf_mutex); if (ov_open(fh, &vf, NULL, 0) == 0) { comment = ov_comment(&vf, -1); if (comment && comment->vendor) vendor = comment->vendor; if ((vi = ov_info(&vf, 0)) != NULL) { bitrate = vi->bitrate_nominal/1000; avgbitrate = ov_bitrate(&vf, -1); if (avgbitrate == OV_EINVAL || avgbitrate == OV_FALSE) avgbitrate = 0; rate = vi->rate; channels = vi->channels; clear_vf = TRUE; } else { bitrate = 0; avgbitrate = 0; rate = 0; channels = 0; } time = ov_time_total(&vf, -1); minutes = time / 60; seconds = time % 60; fseek(fh, 0, SEEK_END); filesize = ftell(fh); label_set_text(bitrate_label, _("Nominal bitrate: %d kbps"), bitrate); label_set_text(avgbitrate_label, _("Average bitrate: %.1f kbps"), ((float) avgbitrate) / 1000); label_set_text(rate_label, _("Samplerate: %d Hz"), rate); label_set_text(channel_label, _("Channels: %d"), channels); label_set_text(length_label, _("Length: %d:%.2d"), minutes, seconds); label_set_text(filesize_label, _("File size: %d B"), filesize); label_set_text(vendor_label, _("Vendor: %s"), vendor); } else fclose(fh); } track_name = get_comment(comment, "title"); performer = get_comment(comment, "artist"); album_name = get_comment(comment, "album"); track_number = get_comment(comment, "tracknumber"); genre = get_comment(comment, "genre"); date = get_comment(comment, "date"); user_comment = get_comment(comment, "comment"); location = get_comment(comment, "location"); description = get_comment(comment, "description"); version = get_comment(comment, "version"); isrc = get_comment(comment, "isrc"); organization = get_comment(comment, "organization"); copyright = get_comment(comment, "copyright"); rg_track_gain = get_comment(comment, "replaygain_track_gain"); if (*rg_track_gain == '\0') { g_free(rg_track_gain); rg_track_gain = get_comment(comment, "rg_radio"); /* Old */ } rg_album_gain = get_comment(comment, "replaygain_album_gain"); if (*rg_album_gain == '\0') { g_free(rg_album_gain); rg_album_gain = get_comment(comment, "rg_audiophile"); /* Old */ } rg_track_peak = get_comment(comment, "replaygain_track_peak"); if (*rg_track_peak == '\0') { g_free(rg_track_peak); rg_track_peak = get_comment(comment, "rg_peak"); /* Old */ } rg_album_peak = get_comment(comment, "replaygain_album_peak"); /* Old had no album peak */ /* ov_clear closes the file */ if (clear_vf) ov_clear(&vf); pthread_mutex_unlock(&vf_mutex); /* Fill it all in .. */ gtk_entry_set_text(GTK_ENTRY(title_entry), track_name); gtk_entry_set_text(GTK_ENTRY(performer_entry), performer); gtk_entry_set_text(GTK_ENTRY(album_entry), album_name); gtk_entry_set_text(GTK_ENTRY(user_comment_entry), user_comment); gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(genre_combo)->entry), genre); gtk_entry_set_text(GTK_ENTRY(tracknumber_entry), track_number); gtk_entry_set_text(GTK_ENTRY(date_entry), date); #ifdef ALL_VORBIS_TAGS gtk_entry_set_text(GTK_ENTRY(version_entry), version); gtk_entry_set_text(GTK_ENTRY(description_entry), description); gtk_entry_set_text(GTK_ENTRY(organization_entry), organization); gtk_entry_set_text(GTK_ENTRY(copyright_entry), copyright); gtk_entry_set_text(GTK_ENTRY(isrc_entry), isrc); gtk_entry_set_text(GTK_ENTRY(location_entry), location); #endif gtk_entry_set_text(GTK_ENTRY(filename_entry), vte.filename); gtk_editable_set_position(GTK_EDITABLE(filename_entry), -1); gtk_entry_set_text(GTK_ENTRY(rg_track_entry), rg_track_gain); gtk_entry_set_text(GTK_ENTRY(rg_album_entry), rg_album_gain); gtk_entry_set_text(GTK_ENTRY(rg_track_peak_entry), rg_track_peak); gtk_editable_set_position(GTK_EDITABLE(rg_track_peak_entry), -1); gtk_entry_set_text(GTK_ENTRY(rg_album_peak_entry), rg_album_peak); gtk_editable_set_position(GTK_EDITABLE(rg_album_peak_entry), -1); if (*rg_track_gain == '\0' && *rg_album_gain == '\0' && *rg_track_peak == '\0' && *rg_album_peak == '\0') { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rg_show_button), FALSE); rg_show_cb(rg_show_button, NULL); } else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rg_show_button), TRUE); tmp = g_strdup_printf(_("File Info - %s"), g_basename(vte.filename)); gtk_window_set_title(GTK_WINDOW(window), tmp); g_free(tmp); /* Cleanup .. */ g_free(track_name); g_free(performer); g_free(album_name); g_free(track_number); g_free(genre); g_free(date); g_free(user_comment); g_free(location); g_free(description); g_free(version); g_free(isrc); g_free(organization); g_free(copyright); g_free(rg_track_gain); g_free(rg_album_gain); g_free(rg_track_peak); g_free(rg_album_peak); }
bool OggImportFileHandle::Import(TrackFactory *trackFactory, Track ***outTracks, int *outNumTracks, Tags *tags) { wxASSERT(mFile->IsOpened()); /* -1 is for the current logical bitstream */ vorbis_info *vi = ov_info(mVorbisFile, -1); vorbis_comment *vc = ov_comment(mVorbisFile, -1); WaveTrack **channels = new WaveTrack *[vi->channels]; int c; for (c = 0; c < vi->channels; c++) { channels[c] = trackFactory->NewWaveTrack(int16Sample, vi->rate); if (vi->channels == 2) { switch (c) { case 0: channels[c]->SetChannel(Track::LeftChannel); channels[c]->SetLinked(true); break; case 1: channels[c]->SetChannel(Track::RightChannel); channels[c]->SetTeamed(true); break; } } else { channels[c]->SetChannel(Track::MonoChannel); } } /* The number of bytes to get from the codec in each run */ #define CODEC_TRANSFER_SIZE 4096 /* The number of samples to read between calls to the callback. * Balance between responsiveness of the GUI and throughput of import. */ #define SAMPLES_PER_CALLBACK 100000 short *mainBuffer = new short[CODEC_TRANSFER_SIZE]; /* determine endianness (clever trick courtesy of Nicholas Devillard, * (http://www.eso.org/~ndevilla/endian/) */ int testvar = 1, endian; if(*(char *)&testvar) endian = 0; // little endian else endian = 1; // big endian /* number of samples currently in each channel's buffer */ bool cancelled = false; long bytesRead = 0; long samplesRead = 0; int bitstream = 0; int samplesSinceLastCallback = 0; // You would think that the stream would already be seeked to 0, and // indeed it is if the file is legit. But I had several ogg files on // my hard drive that have malformed headers, and this added call // causes them to be read correctly. Otherwise they have lots of // zeros inserted at the beginning ov_pcm_seek(mVorbisFile, 0); do { /* get data from the decoder */ bytesRead = ov_read(mVorbisFile, (char *) mainBuffer, CODEC_TRANSFER_SIZE, endian, 2, // word length (2 for 16 bit samples) 1, // signed &bitstream); if (bytesRead < 0) { /* Malformed Ogg Vorbis file. */ /* TODO: Return some sort of meaningful error. */ break; } samplesRead = bytesRead / vi->channels / sizeof(short); /* give the data to the wavetracks */ for (c = 0; c < vi->channels; c++) channels[c]->Append((char *)(mainBuffer + c), int16Sample, samplesRead, vi->channels); samplesSinceLastCallback += samplesRead; if (samplesSinceLastCallback > SAMPLES_PER_CALLBACK) { if( mProgressCallback ) cancelled = mProgressCallback(mUserData, ov_time_tell(mVorbisFile) / ov_time_total(mVorbisFile, bitstream)); samplesSinceLastCallback -= SAMPLES_PER_CALLBACK; } } while (!cancelled && bytesRead != 0 && bitstream == 0); delete[]mainBuffer; bool res = (!cancelled && bytesRead >= 0); if (!res) { for(c = 0; c < vi->channels; c++) { delete channels[c]; } delete[] channels; return false; } *outNumTracks = vi->channels; *outTracks = new Track *[vi->channels]; for (c = 0; c < vi->channels; c++) { channels[c]->Flush(); (*outTracks)[c] = channels[c]; } delete[] channels; if (vc) { tags->Clear(); for (c = 0; c < vc->comments; c++) { wxString comment = UTF8CTOWX(vc->user_comments[c]); tags->SetTag(comment.BeforeFirst(wxT('=')), comment.AfterFirst(wxT('='))); } } return true; }
static DWORD run_test(void *tp) { TestParams *params = (TestParams *)tp; FILE *in = params->in; FILE *out = params->out; FILE *refin = params->refin; FILE *refout = params->refout; int max_samples = params->max_samples; OggVorbis_File vf; int eof=0; int current_section; int maxdiff = 0; int countdiffs = 0; int samples = 0; if(ov_open(in, &vf, NULL, 0) < 0) { Output("Input does not appear to be an Ogg bitstream.\n"); exit(1); } /* Throw the comments plus a few lines about the bitstream we're decoding */ { char **ptr=ov_comment(&vf,-1)->user_comments; vorbis_info *vi=ov_info(&vf,-1); if (out != NULL) { while(*ptr){ Output("%s\n",*ptr); ++ptr; } Output("\nBitstream is %d channel, %ldHz\n",vi->channels,vi->rate); Output("\nDecoded length: %ld samples\n", (long)ov_pcm_total(&vf,-1)); Output("Encoded by: %s\n\n",ov_comment(&vf,-1)->vendor); } } while((!eof) && (max_samples > 0)){ long ret=ov_read(&vf,pcmout,sizeof(pcmout),¤t_section); if (ret == 0) { /* EOF */ eof=1; } else if (ret < 0) { /* error in the stream. Not a problem, just reporting it in case we (the app) cares. In this case, we don't. */ } else { /* we don't bother dealing with sample rate changes, etc, but you'll have to*/ if (out != NULL) { fwrite(pcmout,1,ret,out); } max_samples -= ret>>1; if (refout != NULL) { fwrite(pcmout,1,ret,refout); samples += ret>>1; Output("%d", samples); } if (refin != NULL) { int i, diff; fread(ref,1,ret,refin); for (i=0; i<(ret>>1);i++) { diff = ((short *)pcmout)[i] - ((short *)ref)[i]; if (diff != 0) { if (diff < 0) diff = -diff; if (diff > maxdiff) maxdiff = diff; countdiffs++; if (countdiffs < 50) { Output("samples differ: %x vs %x\n", ((unsigned short *)pcmout)[i], ((unsigned short *)ref)[i]); } else if ((countdiffs % 100) == 0) { Output("%d differences, maximum = %d\n", countdiffs, maxdiff); } } } } }
BOOL decode_vorbis_file(LLVFS *vfs, const LLUUID &in_uuid, char *out_fname) { ov_callbacks vfs_callbacks; vfs_callbacks.read_func = vfs_read; vfs_callbacks.seek_func = vfs_seek; vfs_callbacks.close_func = vfs_close; vfs_callbacks.tell_func = vfs_tell; char pcmout[4096]; /*Flawfinder: ignore*/ unsigned char temp[64]; /*Flawfinder: ignore*/ LLVFile *in_vfile; U32 data_length = 0; llinfos << "Vorbis decode from vfile: " << in_uuid << llendl; in_vfile = new LLVFile(vfs, in_uuid, LLAssetType::AT_SOUND); if (! in_vfile->getSize()) { llwarning("unable to open vorbis source vfile for reading",0); return(FALSE); } apr_file_t* outfp = ll_apr_file_open(out_fname,LL_APR_WPB); if (!outfp) { llwarning("unable to open vorbis destination file for writing",0); return(FALSE); } else { // write the .wav format header //"RIFF" temp[0] = 0x52; temp[1] = 0x49; temp[2] = 0x46; temp[3] = 0x46; // length = datalen + 36 (to be filled in later) temp[4] = 0x00; temp[5] = 0x00; temp[6] = 0x00; temp[7] = 0x00; //"WAVE" temp[8] = 0x57; temp[9] = 0x41; temp[10] = 0x56; temp[11] = 0x45; // "fmt " temp[12] = 0x66; temp[13] = 0x6D; temp[14] = 0x74; temp[15] = 0x20; // chunk size = 16 temp[16] = 0x10; temp[17] = 0x00; temp[18] = 0x00; temp[19] = 0x00; // format (1 = PCM) temp[20] = 0x01; temp[21] = 0x00; // number of channels temp[22] = 0x01; temp[23] = 0x00; // samples per second temp[24] = 0x44; temp[25] = 0xAC; temp[26] = 0x00; temp[27] = 0x00; // average bytes per second temp[28] = 0x88; temp[29] = 0x58; temp[30] = 0x01; temp[31] = 0x00; // bytes to output at a single time temp[32] = 0x02; temp[33] = 0x00; // 16 bits per sample temp[34] = 0x10; temp[35] = 0x00; // "data" temp[36] = 0x64; temp[37] = 0x61; temp[38] = 0x74; temp[39] = 0x61; // these are the length of the data chunk, to be filled in later temp[40] = 0x00; temp[41] = 0x00; temp[42] = 0x00; temp[43] = 0x00; ll_apr_file_write(outfp, temp, 44); } OggVorbis_File vf; int eof=0; int current_section; int r = ov_open_callbacks(in_vfile, &vf, NULL, 0, vfs_callbacks); if(r < 0) { llwarns << r << " Input to vorbis decode does not appear to be an Ogg bitstream: " << in_uuid << llendl; return(FALSE); } { char **ptr=ov_comment(&vf,-1)->user_comments; // vorbis_info *vi=ov_info(&vf,-1); while(*ptr){ fprintf(stderr,"%s\n",*ptr); ++ptr; } // fprintf(stderr,"\nBitstream is %d channel, %ldHz\n",vi->channels,vi->rate); // fprintf(stderr,"\nDecoded length: %ld samples\n", (long)ov_pcm_total(&vf,-1)); // fprintf(stderr,"Encoded by: %s\n\n",ov_comment(&vf,-1)->vendor); } while(!eof){ long ret=ov_read(&vf,pcmout,sizeof(pcmout),0,2,1,¤t_section); if (ret == 0) { /* EOF */ eof=1; // llinfos << "Vorbis EOF" << llendl; } else if (ret < 0) { /* error in the stream. Not a problem, just reporting it in case we (the app) cares. In this case, we don't. */ llwarning("Error in vorbis stream",0); break; } else { // llinfos << "Vorbis read " << ret << "bytes" << llendl; /* we don't bother dealing with sample rate changes, etc, but. you'll have to*/ data_length += ll_apr_file_write(outfp, pcmout, ret); } } ov_clear(&vf); // write "data" chunk length ll_apr_file_seek(outfp,APR_SET,40); ll_apr_file_write(outfp,&data_length,4); // write overall "RIFF" length data_length += 36; ll_apr_file_seek(outfp,APR_SET,4); ll_apr_file_write(outfp,&data_length,1*4); // F**K!!! Vorbis encode/decode messes up loop point transitions (pop) // do a cheap-and-cheesy crossfade S16 *samplep; S32 i; S32 fade_length; fade_length = llmin((S32)128,(S32)(data_length-36)/8); ll_apr_file_seek(outfp,APR_SET,44); ll_apr_file_read(outfp, pcmout,2*fade_length); //read first 16 samples samplep = (S16 *)pcmout; for (i = 0 ;i < fade_length; i++) { *samplep++ = ((F32)*samplep * ((F32)i/(F32)fade_length)); } ll_apr_file_seek(outfp,APR_SET,44); ll_apr_file_write(outfp,pcmout,2*fade_length); //write back xfaded first 16 samples ll_apr_file_seek(outfp,APR_END,-fade_length*2); ll_apr_file_read(outfp, pcmout,2*fade_length); //read last 16 samples samplep = (S16 *)pcmout; for (i = fade_length-1 ; i >= 0; i--) { *samplep++ = ((F32)*samplep * ((F32)i/(F32)fade_length)); } ll_apr_file_seek(outfp,SEEK_END,-fade_length*2); ll_apr_file_write(outfp,pcmout,2*fade_length); //write back xfaded last 16 samples apr_file_close(outfp); if ((36 == data_length) || (!(eof))) { llwarning("BAD Vorbis DECODE!, removing .wav!",0); LLFile::remove(out_fname); return (FALSE); } // fprintf(stderr,"Done.\n"); return(TRUE); }
int main(int argc, char *argv[]){ OggVorbis_File vf; int eof=0; int current_section; FILE *fp; int dev=0; char **ptr; vorbis_info *vi; #ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */ /* Beware the evil ifdef. We avoid these where we can, but this one we cannot. Don't add any more, you'll probably go to hell if you do. */ _setmode( _fileno( stdin ), _O_BINARY ); _setmode( _fileno( stdout ), _O_BINARY ); #endif if(argc < 2) { printf("Usage : ivorbisfile_example <ogg filename>\n"); exit(0); } fp = fopen(argv[1],"rb"); if(fp == NULL) printf("File open error\n"); //if(ov_open(stdin, &vf, NULL, 0) < 0) { if(ov_open(fp, &vf, NULL, 0) < 0) { fprintf(stderr,"Input does not appear to be an Ogg bitstream.\n"); exit(1); } /* Throw the comments plus a few lines about the bitstream we're decoding */ // { ptr=ov_comment(&vf,-1)->user_comments; vi=ov_info(&vf,-1); while(*ptr){ fprintf(stderr,"%s\n",*ptr); ++ptr; //printf(". \n"); } fprintf(stderr,"\nBitstream is %d channel, %ldHz\n",vi->channels,vi->rate); fprintf(stderr,"\nDecoded length: %ld samples\n", (long)ov_pcm_total(&vf,-1)); fprintf(stderr,"Encoded by: %s\n\n",ov_comment(&vf,-1)->vendor); // } if ((dev = open(DEV, O_RDWR)) < 1) { printf("Device open failed"); } #if 1 { int i, v; v = vi->rate/2;//22050; i = ioctl(dev, SNDCTL_DSP_SPEED, &v); fprintf(stderr, "%s(%d): ioctl(SNDCTL_DSP_SPEED)=%d, set=%d\n", __FILE__, __LINE__, i, v); v = 1; i = ioctl(dev, SNDCTL_DSP_STEREO, &v); fprintf(stderr, "%s(%d): ioctl(SNDCTL_DSP_STEREO)=%d, set=%d\n", __FILE__, __LINE__, i, v); v = AFMT_S16_BE; i = ioctl(dev, SNDCTL_DSP_SAMPLESIZE, &v); fprintf(stderr, "%s(%d): ioctl(SNDCTL_DSP_SAMPLESIZE)=%d, set=%d\n", __FILE__, __LINE__, i, v); } #endif #if 0 { int i, v; v = 44100; i = ioctl(fileno(stdout), SNDCTL_DSP_SPEED, &v); fprintf(stderr, "%s(%d): ioctl(SNDCTL_DSP_SPEED)=%d, set=%d\n", __FILE__, __LINE__, i, v); v = 1; i = ioctl(fileno(stdout), SNDCTL_DSP_STEREO, &v); fprintf(stderr, "%s(%d): ioctl(SNDCTL_DSP_STEREO)=%d, set=%d\n", __FILE__, __LINE__, i, v); v = AFMT_S16_BE; i = ioctl(fileno(stdout), SNDCTL_DSP_SAMPLESIZE, &v); fprintf(stderr, "%s(%d): ioctl(SNDCTL_DSP_SAMPLESIZE)=%d, set=%d\n", __FILE__, __LINE__, i, v); } #endif while(!eof){ long ret=ov_read(&vf,pcmout,sizeof(pcmout),¤t_section); // printf("\nRet = %d\n",ret); if (ret == 0) { /* EOF */ eof=1; } else if (ret < 0) { /* error in the stream. Not a problem, just reporting it in case we (the app) cares. In this case, we don't. */ } else { /* we don't bother dealing with sample rate changes, etc, but you'll have to*/ //fwrite(pcmout,1,ret,stdout); write(dev,pcmout,ret); } } /* cleanup */ ov_clear(&vf); fprintf(stderr,"Done.\n"); return(0); }
int OggImportFileHandle::Import(TrackFactory *trackFactory, Track ***outTracks, int *outNumTracks, Tags *tags) { wxASSERT(mFile->IsOpened()); CreateProgress(); //Number of streams used may be less than mVorbisFile->links, //but this way bitstream matches array index. mChannels = new WaveTrack **[mVorbisFile->links]; int i,c; for (i = 0; i < mVorbisFile->links; i++) { //Stream is not used if (mStreamUsage[i] == 0) { //This is just a padding to keep bitstream number and //array indices matched. mChannels[i] = NULL; continue; } vorbis_info *vi = ov_info(mVorbisFile, i); vorbis_comment *vc = ov_comment(mVorbisFile, i); mChannels[i] = new WaveTrack *[vi->channels]; for (c = 0; c < vi->channels; c++) { mChannels[i][c] = trackFactory->NewWaveTrack(int16Sample, vi->rate); if (vi->channels == 2) { switch (c) { case 0: mChannels[i][c]->SetChannel(Track::LeftChannel); mChannels[i][c]->SetLinked(true); break; case 1: mChannels[i][c]->SetChannel(Track::RightChannel); mChannels[i][c]->SetTeamed(true); break; } } else { mChannels[i][c]->SetChannel(Track::MonoChannel); } } } /* The number of bytes to get from the codec in each run */ #define CODEC_TRANSFER_SIZE 4096 /* The number of samples to read between calls to the callback. * Balance between responsiveness of the GUI and throughput of import. */ #define SAMPLES_PER_CALLBACK 100000 short *mainBuffer = new short[CODEC_TRANSFER_SIZE]; /* determine endianness (clever trick courtesy of Nicholas Devillard, * (http://www.eso.org/~ndevilla/endian/) */ int testvar = 1, endian; if(*(char *)&testvar) endian = 0; // little endian else endian = 1; // big endian /* number of samples currently in each channel's buffer */ bool cancelled = false; long bytesRead = 0; long samplesRead = 0; int bitstream = 0; int samplesSinceLastCallback = 0; // You would think that the stream would already be seeked to 0, and // indeed it is if the file is legit. But I had several ogg files on // my hard drive that have malformed headers, and this added call // causes them to be read correctly. Otherwise they have lots of // zeros inserted at the beginning ov_pcm_seek(mVorbisFile, 0); do { /* get data from the decoder */ bytesRead = ov_read(mVorbisFile, (char *) mainBuffer, CODEC_TRANSFER_SIZE, endian, 2, // word length (2 for 16 bit samples) 1, // signed &bitstream); if (bytesRead < 0) { /* Malformed Ogg Vorbis file. */ /* TODO: Return some sort of meaningful error. */ break; } samplesRead = bytesRead / mVorbisFile->vi[bitstream].channels / sizeof(short); /* give the data to the wavetracks */ if (mStreamUsage[bitstream] != 0) { for (c = 0; c < mVorbisFile->vi[bitstream].channels; c++) mChannels[bitstream][c]->Append((char *)(mainBuffer + c), int16Sample, samplesRead, mVorbisFile->vi[bitstream].channels); } samplesSinceLastCallback += samplesRead; if (samplesSinceLastCallback > SAMPLES_PER_CALLBACK) { cancelled = !mProgress->Update(ov_time_tell(mVorbisFile), ov_time_total(mVorbisFile, bitstream)); samplesSinceLastCallback -= SAMPLES_PER_CALLBACK; } } while (!cancelled && bytesRead != 0); delete[]mainBuffer; bool res = (!cancelled && bytesRead >= 0); if (!res) { for (i = 0; i < mVorbisFile->links; i++) { if (mChannels[i]) { for(c = 0; c < mVorbisFile->vi[bitstream].channels; c++) { if (mChannels[i][c]) delete mChannels[i][c]; } delete[] mChannels[i]; } } delete[] mChannels; return (cancelled ? eImportCancelled : eImportFailed); } *outNumTracks = 0; for (int s = 0; s < mVorbisFile->links; s++) { if (mStreamUsage[s] != 0) *outNumTracks += mVorbisFile->vi[s].channels; } *outTracks = new Track *[*outNumTracks]; int trackindex = 0; for (i = 0; i < mVorbisFile->links; i++) { if (mChannels[i]) { for (c = 0; c < mVorbisFile->vi[i].channels; c++) { mChannels[i][c]->Flush(); (*outTracks)[trackindex++] = mChannels[i][c]; } delete[] mChannels[i]; } } delete[] mChannels; //\todo { Extract comments from each stream? } if (mVorbisFile->vc[0].comments > 0) { tags->Clear(); for (c = 0; c < mVorbisFile->vc[0].comments; c++) { wxString comment = UTF8CTOWX(mVorbisFile->vc[0].user_comments[c]); wxString name = comment.BeforeFirst(wxT('=')); wxString value = comment.AfterFirst(wxT('=')); if (name.Upper() == wxT("DATE") && !tags->HasTag(TAG_YEAR)) { long val; if (value.Length() == 4 && value.ToLong(&val)) { name = TAG_YEAR; } } tags->SetTag(name, value); } } return eImportSuccess; }
bool COggVorbisFileHelper::init( std::string fin_str,bool bResample /*= true*/,int nResQuality/*=0*/, char* pData /*= NULL*/, uint32 iSize /*= 0*/) { cleanup(); #if defined(HAVE_PTHREAD) pthread_mutex_lock(&mutex1); #endif nSoundChannel = s3eSoundGetFreeChannel(); if(nSoundChannel == -1) { m_strLastError.clear(); m_strLastError = "Cannot open a sound channel."; s3eDebugTracePrintf("%s\n",m_strLastError.c_str()); cleanup(); #if defined(HAVE_PTHREAD) pthread_mutex_unlock(&mutex1); #endif return false; } s3eSoundChannelRegister(nSoundChannel, S3E_CHANNEL_GEN_AUDIO, GenerateAudioCallback, this); s3eSoundChannelRegister(nSoundChannel, S3E_CHANNEL_END_SAMPLE, EndSampleCallback, this); ov_callbacks callbacks; callbacks.read_func = read_func; callbacks.seek_func = seek_func; callbacks.close_func = close_func; callbacks.tell_func = tell_func; if (pData != NULL) { oggvorbis_filein = s3eFileOpenFromMemory(pData, iSize); } else { if(false /*oggvorbis_filein != NULL*/) { if(s3eFileClose(oggvorbis_filein) == S3E_RESULT_ERROR) { m_strLastError.clear(); m_strLastError = "Cannot close old file"; s3eDebugTracePrintf("%s\n",m_strLastError.c_str()); cleanup(); #if defined(HAVE_PTHREAD) pthread_mutex_unlock(&mutex1); #endif return false; } } oggvorbis_filein = s3eFileOpen(fin_str.c_str(),"rb"); } if(oggvorbis_filein == NULL) { m_strLastError.clear(); m_strLastError = "Cannot open file " + fin_str; s3eDebugTracePrintf("%s\n",m_strLastError.c_str()); cleanup(); #if defined(HAVE_PTHREAD) pthread_mutex_unlock(&mutex1); #endif return false; } if(ov_open_callbacks(oggvorbis_filein, &vf, NULL, 0, callbacks) < 0) { m_strLastError.clear(); m_strLastError = "Input does not appear to be an Ogg bitstream."; s3eDebugTracePrintf("%s\n",m_strLastError.c_str()); cleanup(); #if defined(HAVE_PTHREAD) pthread_mutex_unlock(&mutex1); #endif return false; } /* Throw the comments plus a few lines about the bitstream we're decoding */ { char **ptr=ov_comment(&vf,-1)->user_comments; vorbis_info *vi=ov_info(&vf,-1); //while(*ptr) //{ // fprintf(stderr,"%s\n",*ptr); // ++ptr; //} total_samples = ov_pcm_total(&vf,-1); time_length = ov_time_total_func(&vf,-1); nChannels = vi->channels; nRate = vi->rate; s3eSoundChannelSetInt(nSoundChannel, S3E_CHANNEL_RATE, nRate); nOutputRate = s3eSoundGetInt(S3E_SOUND_OUTPUT_FREQ); int gcd = GCD(nRate, nOutputRate); nW = nRate / gcd; nL = nOutputRate / gcd; dResampleFactor = (float)nOutputRate / (float)vi->rate; // 0 - 4.0 ? int err; bEnableResampling = bResample; nResampleQuality = nResQuality; if(bEnableResampling) { if(res_contL) speex_resampler_destroy(res_contL); res_contL = speex_resampler_init(1,nRate,nOutputRate,nResampleQuality,&err); if(res_contR) speex_resampler_destroy(res_contR); res_contR = speex_resampler_init(1,nRate,nOutputRate,nResampleQuality,&err); if(err != RESAMPLER_ERR_SUCCESS) { m_strLastError.clear(); m_strLastError = "Cannot start resampler."; s3eDebugTracePrintf("%s\n",m_strLastError.c_str()); cleanup(); #if defined(HAVE_PTHREAD) pthread_mutex_unlock(&mutex1); #endif return false; } } else { int fs = min(nRate, nOutputRate); double fc = (fs/2) / (double)nOutputRate; // half the input sample rate (eg nyquist limit of input) // Generate filter coefficients wsfirLP(dFilterCoefficients, nFilterCoefficients, W_BLACKMAN, fc); if(dResampleFactor != 1) s3eDebugErrorShow(S3E_MESSAGE_CONTINUE,"Resample factor not 1 but resampling disabled"); } s3eDebugTracePrintf("\nBitstream is %d channel, %ldHz\n",vi->channels,vi->rate); s3eDebugTracePrintf("\nDecoded length: %ld samples\n",(long)total_samples); s3eDebugTracePrintf("Encoded by: %s\n\n",ov_comment(&vf,-1)->vendor); s3eDebugTracePrintf("Resampling by rational factor %d / %d", nW, nL); } bStopDecoding = false; nStatus = OH_READY; #if defined(HAVE_PTHREAD) pthread_mutex_unlock(&mutex1); #endif return true; }
VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const char * filename, ov_callbacks *callbacks_p, off_t other_header_bytes, const vgm_vorbis_info_t *vgm_inf) { VGMSTREAM * vgmstream = NULL; OggVorbis_File temp_ovf; ogg_vorbis_streamfile temp_streamfile; ogg_vorbis_codec_data * data = NULL; OggVorbis_File *ovf; int inited_ovf = 0; vorbis_info *info; int loop_flag = vgm_inf->loop_flag; int32_t loop_start = vgm_inf->loop_start; int loop_length_found = vgm_inf->loop_length_found; int32_t loop_length = vgm_inf->loop_length; int loop_end_found = vgm_inf->loop_end_found; int32_t loop_end = vgm_inf->loop_end; ov_callbacks default_callbacks; if (!callbacks_p) { default_callbacks.read_func = read_func; default_callbacks.seek_func = seek_func; default_callbacks.close_func = close_func; default_callbacks.tell_func = tell_func; if (vgm_inf->scd_xor != 0) { default_callbacks.read_func = read_func_scd; } callbacks_p = &default_callbacks; } temp_streamfile.streamfile = streamFile; temp_streamfile.offset = 0; temp_streamfile.size = get_streamfile_size(temp_streamfile.streamfile); temp_streamfile.other_header_bytes = other_header_bytes; temp_streamfile.scd_xor = vgm_inf->scd_xor; temp_streamfile.scd_xor_len = vgm_inf->scd_xor_len; /* can we open this as a proper ogg vorbis file? */ memset(&temp_ovf, 0, sizeof(temp_ovf)); if (ov_test_callbacks(&temp_streamfile, &temp_ovf, NULL, 0, *callbacks_p)) goto fail; /* we have to close this as it has the init_vgmstream meta-reading STREAMFILE */ ov_clear(&temp_ovf); /* proceed to open a STREAMFILE just for this stream */ data = calloc(1,sizeof(ogg_vorbis_codec_data)); if (!data) goto fail; data->ov_streamfile.streamfile = streamFile->open(streamFile,filename, STREAMFILE_DEFAULT_BUFFER_SIZE); if (!data->ov_streamfile.streamfile) goto fail; data->ov_streamfile.offset = 0; data->ov_streamfile.size = get_streamfile_size(data->ov_streamfile.streamfile); data->ov_streamfile.other_header_bytes = other_header_bytes; data->ov_streamfile.scd_xor = vgm_inf->scd_xor; data->ov_streamfile.scd_xor_len = vgm_inf->scd_xor_len; /* open the ogg vorbis file for real */ if (ov_open_callbacks(&data->ov_streamfile, &data->ogg_vorbis_file, NULL, 0, *callbacks_p)) goto fail; ovf = &data->ogg_vorbis_file; inited_ovf = 1; data->bitstream = DEFAULT_BITSTREAM; info = ov_info(ovf,DEFAULT_BITSTREAM); /* grab the comments */ { int i; vorbis_comment *comment; comment = ov_comment(ovf,DEFAULT_BITSTREAM); /* search for a "loop_start" comment */ for (i=0;i<comment->comments;i++) { if (strstr(comment->user_comments[i],"loop_start=")== comment->user_comments[i] || strstr(comment->user_comments[i],"LOOP_START=")== comment->user_comments[i] || strstr(comment->user_comments[i],"COMMENT=LOOPPOINT=")== comment->user_comments[i] || strstr(comment->user_comments[i],"LOOPSTART=")== comment->user_comments[i] || strstr(comment->user_comments[i],"um3.stream.looppoint.start=")== comment->user_comments[i] || strstr(comment->user_comments[i],"LOOP_BEGIN=")== comment->user_comments[i] || strstr(comment->user_comments[i],"LoopStart=")== comment->user_comments[i] ) { loop_start=atol(strrchr(comment->user_comments[i],'=')+1); if (loop_start >= 0) loop_flag=1; } else if (strstr(comment->user_comments[i],"LOOPLENGTH=")== comment->user_comments[i]) { loop_length=atol(strrchr(comment->user_comments[i],'=')+1); loop_length_found=1; } else if (strstr(comment->user_comments[i],"title=-lps")== comment->user_comments[i]) { loop_start=atol(comment->user_comments[i]+10); if (loop_start >= 0) loop_flag=1; } else if (strstr(comment->user_comments[i],"album=-lpe")== comment->user_comments[i]) { loop_end=atol(comment->user_comments[i]+10); loop_flag=1; loop_end_found=1; } else if (strstr(comment->user_comments[i],"LoopEnd=")== comment->user_comments[i]) { if(loop_flag) { loop_length=atol(strrchr(comment->user_comments[i],'=')+1)-loop_start; loop_length_found=1; } } else if (strstr(comment->user_comments[i],"LOOP_END=")== comment->user_comments[i]) { if(loop_flag) { loop_length=atol(strrchr(comment->user_comments[i],'=')+1)-loop_start; loop_length_found=1; } } else if (strstr(comment->user_comments[i],"lp=")== comment->user_comments[i]) { sscanf(strrchr(comment->user_comments[i],'=')+1,"%d,%d", &loop_start,&loop_end); loop_flag=1; loop_end_found=1; } } } /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(info->channels,loop_flag); if (!vgmstream) goto fail; /* store our fun extra datas */ vgmstream->codec_data = data; /* fill in the vital statistics */ vgmstream->channels = info->channels; vgmstream->sample_rate = info->rate; /* let's play the whole file */ vgmstream->num_samples = ov_pcm_total(ovf,-1); if (loop_flag) { vgmstream->loop_start_sample = loop_start; if (loop_length_found) vgmstream->loop_end_sample = loop_start+loop_length; else if (loop_end_found) vgmstream->loop_end_sample = loop_end; else vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_flag = loop_flag; if (vgmstream->loop_end_sample > vgmstream->num_samples) vgmstream->loop_end_sample = vgmstream->num_samples; } vgmstream->coding_type = coding_ogg_vorbis; vgmstream->layout_type = vgm_inf->layout_type; vgmstream->meta_type = vgm_inf->meta_type; return vgmstream; /* clean up anything we may have opened */ fail: if (data) { if (inited_ovf) ov_clear(&data->ogg_vorbis_file); if (data->ov_streamfile.streamfile) close_streamfile(data->ov_streamfile.streamfile); free(data); } if (vgmstream) { vgmstream->codec_data = NULL; close_vgmstream(vgmstream); } return NULL; }