예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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;
}
예제 #4
0
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      );
}
예제 #5
0
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;
}
예제 #7
0
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;
}
예제 #8
0
파일: oggfile.c 프로젝트: blabber/oggquiz
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);
}
예제 #9
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();
    }
  }
예제 #11
0
파일: in_vorbis.c 프로젝트: miksago/icecast
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);
}
예제 #12
0
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;
}
예제 #13
0
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;
}
예제 #14
0
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;
}
예제 #15
0
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, &section);
      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;
}
예제 #16
0
/* 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);
}
예제 #17
0
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, &current_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;
}
예제 #18
0
/* 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, &current_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);
}
예제 #19
0
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;
}
예제 #20
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;
	}
}
예제 #21
0
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;
	}
}
예제 #22
0
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;
}
예제 #23
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);
}
예제 #24
0
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;
}
예제 #25
0
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),&current_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);
            }
          }
        }
      }
    }
예제 #26
0
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,&current_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);
}
예제 #27
0
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),&current_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);
}
예제 #28
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;
}
예제 #29
0
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;
}
예제 #30
0
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;
}