Example #1
0
 int __declspec(dllexport) DLL_FillBuffer(long vgm, char* szBuffer, int iSize)
 {
   VGMSTREAM* song = (VGMSTREAM*)vgm;
   render_vgmstream((sample*)szBuffer,iSize/(2*song->channels),(VGMSTREAM*)vgm);
   
   return iSize;
 }
int64_t Seek(void* context, int64_t time)
{
  if (!context)
    return 0;

  VGMContext* ctx = (VGMContext*)context;
  int16_t* buffer = new int16_t[576*ctx->stream->channels];
  if (!buffer)
    return 0;

  long samples_to_do = (long)time * ctx->stream->sample_rate / 1000L;
  if (samples_to_do < ctx->stream->current_sample )
     reset_vgmstream(ctx->stream);
  else
    samples_to_do -= ctx->stream->current_sample;
      
  while (samples_to_do > 0)
  {
    long l = samples_to_do>576?576:samples_to_do;
    render_vgmstream(buffer, l, ctx->stream);
    samples_to_do -= l;
  }
  delete[] buffer;

  return time;
}
Example #3
0
void render_vgmstream_scd_int(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
    sample interleave_buf[INTERLEAVE_BUF_SIZE];
    int32_t samples_done = 0;
    scd_int_codec_data *data = vgmstream->codec_data;

    while (samples_done < sample_count)
    {
        int32_t samples_to_do = INTERLEAVE_BUF_SIZE;
        int c;
        if (samples_to_do > sample_count - samples_done)
            samples_to_do = sample_count - samples_done;

        for (c=0; c < data->substream_count; c++)
        {
            int32_t i;

            render_vgmstream(interleave_buf,
                    samples_to_do, data->substreams[c]);

            for (i=0; i < samples_to_do; i++)
            {
                buffer[(samples_done+i)*data->substream_count + c] = interleave_buf[i];
            }
        }

        samples_done += samples_to_do;

    }
}
Example #4
0
/* Decodes samples for segmented streams.
 * Chains together sequential vgmstreams, for data divided into separate sections or files
 * (like one part for intro and other for loop segments, which may even use different codecs). */
void render_vgmstream_segmented(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
    int samples_written = 0;
    segmented_layout_data *data = vgmstream->layout_data;


    while (samples_written < sample_count) {
        int samples_to_do;
        int samples_this_block = data->segments[data->current_segment]->num_samples;


        if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
            /* handle looping, finding loop segment */
            int loop_segment = 0, samples = 0, loop_samples_skip = 0;
            while (samples < vgmstream->num_samples) {
                int32_t segment_samples = data->segments[loop_segment]->num_samples;
                if (vgmstream->loop_start_sample >= samples && vgmstream->loop_start_sample < samples + segment_samples) {
                    loop_samples_skip = vgmstream->loop_start_sample - samples;
                    break; /* loop_start falls within loop_segment's samples */
                }
                samples += segment_samples;
                loop_segment++;
            }
            if (loop_segment == data->segment_count) {
                VGM_LOG("segmented_layout: can't find loop segment\n");
                loop_segment = 0;
            }
            if (loop_samples_skip > 0) {
                VGM_LOG("segmented_layout: loop starts after %i samples\n", loop_samples_skip);
                //todo skip/fix, but probably won't happen
            }

            data->current_segment = loop_segment;
            reset_vgmstream(data->segments[data->current_segment]);
            vgmstream->samples_into_block = 0;
            continue;
        }

        samples_to_do = vgmstream_samples_to_do(samples_this_block, sample_count, vgmstream);
        if (samples_to_do > sample_count - samples_written)
            samples_to_do = sample_count - samples_written;

        /* detect segment change and restart */
        if (samples_to_do == 0) {
            data->current_segment++;
            reset_vgmstream(data->segments[data->current_segment]);
            vgmstream->samples_into_block = 0;
            continue;
        }

        render_vgmstream(&buffer[samples_written*data->segments[data->current_segment]->channels],
                samples_to_do,data->segments[data->current_segment]);

        samples_written += samples_to_do;
        vgmstream->current_sample += samples_to_do;
        vgmstream->samples_into_block += samples_to_do;
    }
}
int ReadPCM(void* context, uint8_t* pBuffer, int size, int *actualsize)
{
  if (!context || !actualsize)
    return 1;

  VGMContext* ctx = (VGMContext*)context;

  render_vgmstream((sample*)pBuffer, size/(2*ctx->stream->channels), ctx->stream);
  *actualsize = size;

  ctx->pos += size;
  return 0;
}
Example #6
0
  unsigned long __declspec(dllexport) DLL_Seek(long vgm, unsigned long timepos)
  {
    VGMSTREAM* song = (VGMSTREAM*)vgm;
    int16_t* buffer = new int16_t[576*song->channels];
    long samples_to_do = (long)timepos * song->sample_rate / 1000L;
    if (samples_to_do < song->current_sample )
       reset_vgmstream(song);
    else
      samples_to_do -= song->current_sample;
      
    while (samples_to_do > 0)
    {
      long l = samples_to_do>576?576:samples_to_do;
      render_vgmstream(buffer,l,song);
      samples_to_do -= l;
    }
    delete[] buffer;

    return timepos;
  }
Example #7
0
int __stdcall XMP_Buffer(float* buffer, UINT32 bufsize) {
	int i,x,y;
	int adder = vgmstream->channels * (Decoder_Is_Using_Lame_Hack ? 2 : 1);

	/*
	** Algorithm for correct playback.
	** This is in fact a huge-ass hack which is terrible and crashes tracks with sample rates
	** it doesn't like. We'll need to fix this later
	*/


	for (i=0;i<bufsize;i+=adder) {
		INT16 buf[16];
		memset(buf,0,16 * 2);

		render_vgmstream(buf,vgmstream->channels,vgmstream);
		for (x=0;x<adder;x++) {	
			for (y=0;y<(Decoder_Is_Using_Lame_Hack ? 2 : 1);y++)
				*(buffer + i + x + y) = (float)(buf[x]) / 22050; // This divide is required, audio is REALLY LOUD otherwise
		}
	}

	return bufsize;
}
Example #8
0
void decodeThread(void* arg)
{
    debug("decode_buffer start\n");
    stream_filename* strm_file = static_cast<stream_filename*>(arg);
    VGMSTREAM* vgmstream = strm_file->stream;
    std::string& filename = strm_file->filename;

    if (!vgmstream)
        return;

    const int channels = vgmstream->channels;
    const u32 stream_samples_amount = get_vgmstream_play_samples(1, 0, 0, vgmstream);
    u32 current_sample_pos = 0;
    stream_buffer* buffer = &playBuffer1;

    while (runThreads)
    {
        debug("decode_buffer wait produce\n");
        // Wait for signal to make another stream
        svcWaitSynchronization(bufferReadyProduceRequest, U64_MAX);
        svcClearEvent(bufferReadyProduceRequest);

        u32 toget = max_samples;

        if (!vgmstream->loop_flag)
        {
            if (current_sample_pos >= stream_samples_amount)
                break;
            if (current_sample_pos + toget > stream_samples_amount)
                toget = stream_samples_amount - current_sample_pos;
        }

        debug("decode_buffer decode %d\n", toget);
        // TODO modify render_vgmstream to return not decode channel data sequentially in the buffer passed in.
        render_vgmstream(rawSampleBuffer, toget, vgmstream);

        debug("decode_buffer detangle\n");
        // Detangle audio data...
        buffer->samples = toget;
        for (u32 i = 0; i < max_samples; i++)
        {
            for (int j = 0; j < channels; j++)
            {
                buffer->channels[j][i] = rawSampleBuffer[i * channels + j];
            }
        }

        debug("decode_buffer signal consume\n");
        // Ready to play
        svcSignalEvent(bufferReadyConsumeRequest);

        clearTopScreen();
        print("\x1b[1;0HCurrently playing %s\nPress B to choose another song\nPress Start to exit", filename.c_str());
        print("\x1b[29;0HPLAYING %.4lf %.4lf\n", (float)current_sample_pos / vgmstream->sample_rate, (float)stream_samples_amount / vgmstream->sample_rate);
        current_sample_pos += toget;

        // Flip buffers
        if (buffer == &playBuffer1)
            buffer = &playBuffer2;
        else
            buffer = &playBuffer1;

        debug("decode_buffer decode more\n");
    }
    debug("decode_buffer done\n");
}
Example #9
0
static int play_vgmstream(const char *filename, struct params *par) {
    int ret = 0;
    STREAMFILE *sf;
    VGMSTREAM *vgms;
    FILE *save_fps[4];
    int loop_count;
    int64_t total_samples;
    size_t buffer_size;
    int64_t buffer_samples;
    int64_t fade_time_samples, fade_start;
    int time_total_min;
    double time_total_sec;
    int64_t s;
    int i;

    sf = open_stdio_streamfile(filename);
    if (!sf) {
        fprintf(stderr, "%s: cannot open file\n", filename);
        return -1;
    }

    sf->stream_index = par->stream_index;
    vgms = init_vgmstream_from_STREAMFILE(sf);
    close_streamfile(sf);

    if (!vgms) {
        fprintf(stderr, "%s: error opening stream\n", filename);
        return -1;
    }

    printf("Playing stream: %s\n", filename);

    /* Print metadata in verbose mode
     */
    if (verbose) {
        char description[4096] = { '\0' };
        describe_vgmstream(vgms, description, sizeof(description));
        puts(description);
        putchar('\n');
    }

    /* If the audio device hasn't been opened yet, then describe it
     */
    if (!device) {
        ao_info *info = ao_driver_info(driver_id);
        printf("Audio device: %s\n", info->name);
        printf("Comment: %s\n", info->comment);
        putchar('\n');
    }

    /* Stupid hack to hang onto a few low-numbered file descriptors
     * so that play_compressed_file() doesn't break, due to POSIX
     * wackiness like https://bugs.debian.org/590920
     */
    for (i = 0; i < 4; i++)
        save_fps[i] = fopen("/dev/null", "r");

    ret = set_sample_format(vgms);
    if (ret) goto fail;

    loop_count = par->loop_count;

    if (vgms->loop_flag && loop_count < 0) {
        /*
         * Calculate how many loops are needed to achieve a minimum
         * playback time. Note: This calculation is derived from the
         * logic in get_vgmstream_play_samples().
         */
        double intro = (double)vgms->loop_start_sample / vgms->sample_rate;
        double loop = (double)(vgms->loop_end_sample - vgms->loop_start_sample) / vgms->sample_rate;
        double end = par->fade_time + par->fade_delay;
        if (loop < 1.0) loop = 1.0;
        loop_count = (int)((par->min_time - intro - end) / loop + 0.99);
        if (loop_count < 1) loop_count = 1;
    }

    total_samples = get_vgmstream_play_samples(loop_count, par->fade_time, par->fade_delay, vgms);

    {
        double total = (double)total_samples / vgms->sample_rate;
        time_total_min = (int)total / 60;
        time_total_sec = total - 60 * time_total_min;
    }

    /* Buffer size in bytes
     */
    buffer_size = 1024 * buffer_size_kb;

    if (!buffer) {
        if (buffer_size_kb < 1) {
            fprintf(stderr, "Invalid buffer size '%d'\n", buffer_size_kb);
            return -1;
        }

        buffer = malloc(buffer_size);
        if (!buffer) goto fail;
    }

    buffer_samples = buffer_size / (vgms->channels * sizeof(sample));

    fade_time_samples = (int64_t)(par->fade_time * vgms->sample_rate);
    fade_start = total_samples - fade_time_samples;
    if (fade_start < 0)
        fade_start = total_samples;

    for (s = 0; s < total_samples && !interrupted; s += buffer_samples) {
        int64_t buffer_used_samples = MIN(buffer_samples, total_samples - s);
        char *suffix = "";

        render_vgmstream(buffer, buffer_used_samples, vgms);

#ifdef LITTLE_ENDIAN_OUTPUT
        swap_samples_le(buffer, vgms->channels * buffer_used_samples);
#endif

        if (vgms->loop_flag && fade_time_samples > 0 && s >= fade_start) {
            /* Got to do the fade-out ourselves :p */
            int64_t b;
            for (b = 0; b < buffer_used_samples; b++) {
                double factor = 1.0 - (double)(s + b - fade_start) / fade_time_samples;
                int c;
                for (c = 0; c < vgms->channels; c++)
                    buffer[vgms->channels * b + c] *= factor;
            }
            suffix = " (fading)";
        }

        if (verbose && !out_filename) {
            double played = (double)s / vgms->sample_rate;
            double remain = (double)(total_samples - s) / vgms->sample_rate;

            int time_played_min = (int)played / 60;
            double time_played_sec = played - 60 * time_played_min;
            int time_remain_min = (int)remain / 60;
            double time_remain_sec = remain - 60 * time_remain_min;

            /* Time: 01:02.34 [08:57.66] of 10:00.00 */
            printf("\rTime: %02d:%05.2f [%02d:%05.2f] of %02d:%05.2f%s ",
                time_played_min, time_played_sec,
                time_remain_min, time_remain_sec,
                time_total_min,  time_total_sec,
                suffix);

            fflush(stdout);
        }

        if (!ao_play(device, (char *)buffer, buffer_used_samples * vgms->channels * sizeof(sample))) {
            fputs("\nAudio playback error\n", stderr);
            ao_close(device);
            device = NULL;
            ret = -1;
            break;
        }
    }

    if (verbose && !ret) {
        /* Clear time status line */
        putchar('\r');
        for (i = 0; i < 64; i++)
            putchar(' ');
        putchar('\r');
        fflush(stdout);
    }

    if (out_filename && !ret)
        printf("Wrote %02d:%05.2f of audio to %s\n\n",
            time_total_min, time_total_sec, out_filename);

    if (interrupted) {
        fputs("Playback terminated.\n\n", stdout);
        ret = record_interrupt();
        if (ret) fputs("Exiting...\n", stdout);
    }

    fail:

    close_vgmstream(vgms);

    for (i = 0; i < 4; i++)
        fclose(save_fps[i]);

    return ret;
}