void psf2_update(unsigned char *buffer, long count) { if (! buffer || aud_input_check_stop ()) { stop_flag = TRUE; return; } int seek = aud_input_check_seek (); if (seek >= 0) { f->seek (seek); return; } aud_input_write_audio (buffer, count); }
static gboolean vorbis_play (const gchar * filename, VFSFile * file) { if (file == NULL) return FALSE; vorbis_info *vi; OggVorbis_File vf; gint last_section = -1; ReplayGainInfo rg_info; gfloat pcmout[PCM_BUFSIZE*sizeof(float)], **pcm; gint bytes, channels, samplerate, br; gchar * title = NULL; memset(&vf, 0, sizeof(vf)); gboolean error = FALSE; if (ov_open_callbacks (file, & vf, NULL, 0, vfs_is_streaming (file) ? vorbis_callbacks_stream : vorbis_callbacks) < 0) { error = TRUE; goto play_cleanup; } vi = ov_info(&vf, -1); if (vi->channels > 2) goto play_cleanup; br = vi->bitrate_nominal; channels = vi->channels; samplerate = vi->rate; aud_input_set_bitrate (br); if (!aud_input_open_audio(FMT_FLOAT, samplerate, channels)) { error = TRUE; goto play_cleanup; } vorbis_update_replaygain(&vf, &rg_info); aud_input_set_gain (& rg_info); /* * Note that chaining changes things here; A vorbis file may * be a mix of different channels, bitrates and sample rates. * You can fetch the information for any section of the file * using the ov_ interface. */ while (! aud_input_check_stop ()) { int seek_value = aud_input_check_seek(); if (seek_value >= 0 && ov_time_seek (& vf, (double) seek_value / 1000) < 0) { fprintf (stderr, "vorbis: seek failed\n"); error = TRUE; break; } gint current_section = last_section; bytes = ov_read_float(&vf, &pcm, PCM_FRAMES, ¤t_section); if (bytes == OV_HOLE) continue; if (bytes <= 0) break; bytes = vorbis_interleave_buffer (pcm, bytes, channels, pcmout); { /* try to detect when metadata has changed */ vorbis_comment * comment = ov_comment (& vf, -1); const gchar * new_title = (comment == NULL) ? NULL : vorbis_comment_query (comment, "title", 0); if (new_title != NULL && (title == NULL || strcmp (title, new_title))) { g_free (title); title = g_strdup (new_title); aud_input_set_tuple (get_tuple_for_vorbisfile (& vf, filename)); } } if (current_section != last_section) { /* * The info struct is different in each section. vf * holds them all for the given bitstream. This * requests the current one */ vi = ov_info(&vf, -1); if (vi->channels > 2) goto stop_processing; if (vi->rate != samplerate || vi->channels != channels) { samplerate = vi->rate; channels = vi->channels; if (!aud_input_open_audio(FMT_FLOAT, vi->rate, vi->channels)) { error = TRUE; goto stop_processing; } vorbis_update_replaygain(&vf, &rg_info); aud_input_set_gain (& rg_info); /* audio reopened */ } } aud_input_write_audio (pcmout, bytes); stop_processing: if (current_section != last_section) { aud_input_set_bitrate (br); last_section = current_section; } } /* main loop */ play_cleanup: ov_clear(&vf); g_free (title); return ! error; }
static gboolean vtx_play(const gchar * filename, VFSFile * file) { gboolean eof = FALSE; void *stream; /* pointer to current position in sound buffer */ guchar regs[14]; gint need; gint left; /* how many sound frames can play with current AY register frame */ gint donow; gint rate; left = 0; rate = chans * (bits / 8); memset(&ay, 0, sizeof(ay)); if (!ayemu_vtx_open(&vtx, filename)) { g_print("libvtx: Error read vtx header from %s\n", filename); return FALSE; } else if (!ayemu_vtx_load_data(&vtx)) { g_print("libvtx: Error read vtx data from %s\n", filename); return FALSE; } ayemu_init(&ay); ayemu_set_chip_type(&ay, vtx.hdr.chiptype, NULL); ayemu_set_chip_freq(&ay, vtx.hdr.chipFreq); ayemu_set_stereo(&ay, vtx.hdr.stereo, NULL); if (aud_input_open_audio(FMT_S16_NE, freq, chans) == 0) { g_print("libvtx: output audio error!\n"); return FALSE; } aud_input_set_bitrate(14 * 50 * 8); while (!aud_input_check_stop() && !eof) { /* (time in sec) * 50 = offset in AY register data frames */ int seek_value = aud_input_check_seek(); if (seek_value >= 0) vtx.pos = seek_value / 20; /* fill sound buffer */ stream = sndbuf; for (need = SNDBUFSIZE / rate; need > 0; need -= donow) { if (left > 0) { /* use current AY register frame */ donow = (need > left) ? left : need; left -= donow; stream = ayemu_gen_sound(&ay, (char *)stream, donow * rate); } else { /* get next AY register frame */ if (ayemu_vtx_get_next_frame(&vtx, (char *)regs) == 0) { donow = need; memset(stream, 0, donow * rate); eof = TRUE; } else { left = freq / vtx.hdr.playerFreq; ayemu_set_regs(&ay, regs); donow = 0; } } } aud_input_write_audio(sndbuf, SNDBUFSIZE); } ayemu_vtx_free(&vtx); return TRUE; }
static gboolean ffaudio_play (const gchar * filename, VFSFile * file) { AUDDBG ("Playing %s.\n", filename); if (! file) return FALSE; AVPacket pkt = {.data = NULL}; gint errcount; gboolean codec_opened = FALSE; gint out_fmt; gboolean planar; gboolean seekable; gboolean error = FALSE; void *buf = NULL; gint bufsize = 0; AVFormatContext * ic = open_input_file (filename, file); if (! ic) return FALSE; CodecInfo cinfo; if (! find_codec (ic, & cinfo)) { fprintf (stderr, "ffaudio: No codec found for %s.\n", filename); goto error_exit; } AUDDBG("got codec %s for stream index %d, opening\n", cinfo.codec->name, cinfo.stream_idx); if (avcodec_open2 (cinfo.context, cinfo.codec, NULL) < 0) goto error_exit; codec_opened = TRUE; switch (cinfo.context->sample_fmt) { case AV_SAMPLE_FMT_U8: out_fmt = FMT_U8; planar = FALSE; break; case AV_SAMPLE_FMT_S16: out_fmt = FMT_S16_NE; planar = FALSE; break; case AV_SAMPLE_FMT_S32: out_fmt = FMT_S32_NE; planar = FALSE; break; case AV_SAMPLE_FMT_FLT: out_fmt = FMT_FLOAT; planar = FALSE; break; case AV_SAMPLE_FMT_U8P: out_fmt = FMT_U8; planar = TRUE; break; case AV_SAMPLE_FMT_S16P: out_fmt = FMT_S16_NE; planar = TRUE; break; case AV_SAMPLE_FMT_S32P: out_fmt = FMT_S32_NE; planar = TRUE; break; case AV_SAMPLE_FMT_FLTP: out_fmt = FMT_FLOAT; planar = TRUE; break; default: fprintf (stderr, "ffaudio: Unsupported audio format %d\n", (int) cinfo.context->sample_fmt); goto error_exit; } /* Open audio output */ AUDDBG("opening audio output\n"); if (aud_input_open_audio(out_fmt, cinfo.context->sample_rate, cinfo.context->channels) <= 0) { error = TRUE; goto error_exit; } AUDDBG("setting parameters\n"); aud_input_set_bitrate(ic->bit_rate); errcount = 0; seekable = ffaudio_codec_is_seekable(cinfo.codec); while (! aud_input_check_stop ()) { int seek_value = aud_input_check_seek (); if (seek_value >= 0 && seekable) { if (av_seek_frame (ic, -1, (gint64) seek_value * AV_TIME_BASE / 1000, AVSEEK_FLAG_ANY) < 0) { _ERROR("error while seeking\n"); } else errcount = 0; seek_value = -1; } AVPacket tmp; gint ret; /* Read next frame (or more) of data */ if ((ret = av_read_frame(ic, &pkt)) < 0) { if (ret == AVERROR_EOF) { AUDDBG("eof reached\n"); break; } else { if (++errcount > 4) { _ERROR("av_read_frame error %d, giving up.\n", ret); break; } else continue; } } else errcount = 0; /* Ignore any other substreams */ if (pkt.stream_index != cinfo.stream_idx) { av_free_packet(&pkt); continue; } /* Decode and play packet/frame */ memcpy(&tmp, &pkt, sizeof(tmp)); while (tmp.size > 0 && ! aud_input_check_stop ()) { /* Check for seek request and bail out if we have one */ if (seek_value < 0) seek_value = aud_input_check_seek (); if (seek_value >= 0) break; #if CHECK_LIBAVCODEC_VERSION (55, 28, 1) AVFrame * frame = av_frame_alloc (); #else AVFrame * frame = avcodec_alloc_frame (); #endif int decoded = 0; int len = avcodec_decode_audio4 (cinfo.context, frame, & decoded, & tmp); if (len < 0) { fprintf (stderr, "ffaudio: decode_audio() failed, code %d\n", len); break; } tmp.size -= len; tmp.data += len; if (! decoded) continue; gint size = FMT_SIZEOF (out_fmt) * cinfo.context->channels * frame->nb_samples; if (planar) { if (bufsize < size) { buf = g_realloc (buf, size); bufsize = size; } audio_interlace ((const void * *) frame->data, out_fmt, cinfo.context->channels, buf, frame->nb_samples); aud_input_write_audio (buf, size); } else aud_input_write_audio (frame->data[0], size); #if CHECK_LIBAVCODEC_VERSION (55, 28, 1) av_frame_free (& frame); #else avcodec_free_frame (& frame); #endif } if (pkt.data) av_free_packet(&pkt); } error_exit: if (pkt.data) av_free_packet(&pkt); if (codec_opened) avcodec_close(cinfo.context); if (ic != NULL) close_input_file(ic); g_free (buf); return ! error; }
static bool_t flac_play (const char * filename, VFSFile * file) { if (!file) return FALSE; void * play_buffer = NULL; bool_t error = FALSE; info->fd = file; if (read_metadata(decoder, info) == FALSE) { FLACNG_ERROR("Could not prepare file for playing!\n"); error = TRUE; goto ERR_NO_CLOSE; } play_buffer = g_malloc (BUFFER_SIZE_BYTE); if (! aud_input_open_audio (SAMPLE_FMT (info->bits_per_sample), info->sample_rate, info->channels)) { error = TRUE; goto ERR_NO_CLOSE; } aud_input_set_bitrate(info->bitrate); while (FLAC__stream_decoder_get_state(decoder) != FLAC__STREAM_DECODER_END_OF_STREAM) { if (aud_input_check_stop ()) break; int seek_value = aud_input_check_seek (); if (seek_value >= 0) FLAC__stream_decoder_seek_absolute (decoder, (int64_t) seek_value * info->sample_rate / 1000); /* Try to decode a single frame of audio */ if (FLAC__stream_decoder_process_single(decoder) == FALSE) { FLACNG_ERROR("Error while decoding!\n"); error = TRUE; break; } squeeze_audio(info->output_buffer, play_buffer, info->buffer_used, info->bits_per_sample); aud_input_write_audio(play_buffer, info->buffer_used * SAMPLE_SIZE(info->bits_per_sample)); reset_info(info); } ERR_NO_CLOSE: g_free (play_buffer); reset_info(info); if (FLAC__stream_decoder_flush(decoder) == FALSE) FLACNG_ERROR("Could not flush decoder state!\n"); return ! error; }