static gboolean tone_play(const gchar *filename, VFSFile *file) { GArray *frequencies; gfloat data[BUF_SAMPLES]; gsize i; gboolean error = FALSE; struct { gdouble wd; guint period, t; } *tone = NULL; frequencies = tone_filename_parse(filename); if (frequencies == NULL) return FALSE; if (aud_input_open_audio(FMT_FLOAT, OUTPUT_FREQ, 1) == 0) { error = TRUE; goto error_exit; } aud_input_set_bitrate(16 * OUTPUT_FREQ); tone = g_malloc(frequencies->len * sizeof(*tone)); for (i = 0; i < frequencies->len; i++) { gdouble f = g_array_index(frequencies, gdouble, i); tone[i].wd = 2 * PI * f / OUTPUT_FREQ; tone[i].period = (G_MAXINT * 2U / OUTPUT_FREQ) * (OUTPUT_FREQ / f); tone[i].t = 0; } while (!aud_input_check_stop()) { for (i = 0; i < BUF_SAMPLES; i++) { gsize j; double sum_sines; for (sum_sines = 0, j = 0; j < frequencies->len; j++) { sum_sines += sin(tone[j].wd * tone[j].t); if (tone[j].t > tone[j].period) tone[j].t -= tone[j].period; tone[j].t++; } /* dithering can cause a little bit of clipping */ data[i] = (sum_sines * 0.999 / (gdouble) frequencies->len); } aud_input_write_audio(data, BUF_BYTES); } error_exit: g_array_free(frequencies, TRUE); g_free(tone); return !error; }
static bool_t psf2_play(const char * filename, VFSFile * file) { void *buffer; int64_t size; PSFEngine eng; bool_t error = FALSE; const char * slash = strrchr (filename, '/'); if (! slash) return FALSE; SNCOPY (dirbuf, filename, slash + 1 - filename); dirpath = dirbuf; vfs_file_get_contents (filename, & buffer, & size); eng = psf_probe(buffer); if (eng == ENG_NONE || eng == ENG_COUNT) { free(buffer); return FALSE; } f = &psf_functor_map[eng]; if (f->start(buffer, size) != AO_SUCCESS) { free(buffer); return FALSE; } aud_input_open_audio(FMT_S16_NE, 44100, 2); aud_input_set_bitrate(44100*2*2*8); stop_flag = FALSE; f->execute(); f->stop(); f = NULL; dirpath = NULL; free(buffer); return ! error; }
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 bool_t metronom_play (const char * filename, VFSFile * file) { metronom_t pmetronom; int16_t data[BUF_SAMPLES]; int t = 0, tact, num; int datagoal = 0; int datamiddle = 0; int datacurrent = datamiddle; int datalast = datamiddle; int data_form[TACT_FORM_MAX]; if (aud_input_open_audio(FMT_S16_NE, AUDIO_FREQ, 1) == 0) return FALSE; if (!metronom_get_cp(filename, &pmetronom, NULL)) { fprintf (stderr, "Invalid metronom tact parameters in URI %s", filename); return FALSE; } aud_input_set_bitrate(sizeof(data[0]) * 8 * AUDIO_FREQ); tact = 60 * AUDIO_FREQ / pmetronom.bpm; /* prepare weighted amplitudes */ for (num = 0; num < pmetronom.num; num++) { data_form[num] = MAX_AMPL * tact_form[pmetronom.id][num]; } num = 0; while (!aud_input_check_stop()) { int i; for (i = 0; i < BUF_SAMPLES; i++) { if (t == tact) { t = 0; datagoal = data_form[num]; } else if (t == 10) { datagoal = -data_form[num]; } else if (t == 25) { datagoal = data_form[num]; /* circle through weighted amplitudes */ num++; if (num >= pmetronom.num) num = 0; } /* makes curve a little bit smoother */ data[i] = (datalast + datacurrent + datagoal) / 3; datalast = datacurrent; datacurrent = data[i]; if (t > 35) datagoal = (datamiddle + 7 * datagoal) / 8; t++; } aud_input_write_audio(data, BUF_BYTES); } return TRUE; }
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; }