/** * 装载TTA音乐文件 * * @param spath 短路径名 * @param lpath 长路径名 * * @return 成功时返回0 */ static int tta_load(const char *spath, const char *lpath) { __init(); if (tta_read_tag(spath) != 0) { __end(); return -1; } if (g_buff != NULL) { free(g_buff); g_buff = NULL; } g_buff = calloc(TTA_BUFFER_SIZE, sizeof(*g_buff)); if (g_buff == NULL) { __end(); return -1; } if (open_tta_file(spath, &ttainfo, 0, g_io_buffer_size) < 0) { dbg_printf(d, "TTA Decoder Error - %s", get_error_str(ttainfo.STATE)); close_tta_file(&ttainfo); return -1; } if (player_init(&ttainfo) != 0) { __end(); return -1; } if (ttainfo.BPS == 0) { __end(); return -1; } g_info.samples = ttainfo.DATALENGTH; g_info.duration = (double) ttainfo.LENGTH; g_info.sample_freq = ttainfo.SAMPLERATE; g_info.channels = ttainfo.NCH; g_info.filesize = ttainfo.FILESIZE; if (xAudioInit() < 0) { __end(); return -1; } if (xAudioSetFrequency(ttainfo.SAMPLERATE) < 0) { __end(); return -1; } xAudioSetChannelCallback(0, tta_audiocallback, NULL); generic_lock(); g_status = ST_LOADED; generic_unlock(); return 0; }
static void Done(tta* p) { free(p->Buffer); p->Buffer = NULL; close_tta_file(&p->Decoder); player_stop(); }
static void tta_free (DB_fileinfo_t *_info) { tta_info_t *info = (tta_info_t *)_info; if (info) { player_stop (&info->tta); close_tta_file (&info->tta); free (info); } }
static DB_playItem_t * tta_insert (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname) { tta_info tta; if (open_tta_file (fname, &tta, 0) != 0) { fprintf (stderr, "tta: failed to open %s\n", fname); return NULL; } // if (tta.BPS != 16) { // fprintf (stderr, "tta: only 16 bit is supported yet, skipped %s\n", fname); // return NULL; // } int totalsamples = tta.DATALENGTH; double dur = tta.LENGTH; DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id); deadbeef->pl_add_meta (it, ":FILETYPE", "TTA"); deadbeef->plt_set_item_duration (plt, it, dur); close_tta_file (&tta); DB_FILE *fp = deadbeef->fopen (fname); int64_t fsize = -1; if (fp) { fsize = deadbeef->fgetlength (fp); /*int apeerr = */deadbeef->junk_apev2_read (it, fp); /*int v2err = */deadbeef->junk_id3v2_read (it, fp); /*int v1err = */deadbeef->junk_id3v1_read (it, fp); deadbeef->fclose (fp); } char s[100]; snprintf (s, sizeof (s), "%lld", fsize); deadbeef->pl_add_meta (it, ":FILE_SIZE", s); snprintf (s, sizeof (s), "%d", tta.BPS); deadbeef->pl_add_meta (it, ":BPS", s); snprintf (s, sizeof (s), "%d", tta.NCH); deadbeef->pl_add_meta (it, ":CHANNELS", s); snprintf (s, sizeof (s), "%d", tta.SAMPLERATE); deadbeef->pl_add_meta (it, ":SAMPLERATE", s); snprintf (s, sizeof (s), "%d", tta.BITRATE); deadbeef->pl_add_meta (it, ":BITRATE", s); DB_playItem_t *cue = deadbeef->plt_process_cue (plt, after, it, totalsamples, tta.SAMPLERATE); if (cue) { deadbeef->pl_item_unref (it); return cue; } deadbeef->pl_add_meta (it, "title", NULL); after = deadbeef->plt_insert_item (plt, after, it); deadbeef->pl_item_unref (it); return after; }
/** * 停止TTA音乐文件的播放,销毁所占有的线程、资源等 * * @note 不可以在播放线程中调用,必须能够多次重复调用而不死机 * * @return 成功时返回0 */ static int tta_end(void) { __end(); xAudioEnd(); if (g_buff != NULL) { free(g_buff); g_buff = NULL; } player_stop(); close_tta_file(&ttainfo); g_status = ST_STOPPED; generic_end(); return 0; }