예제 #1
0
파일: gme.c 프로젝트: 0xheart0/vlc
static int Demux (demux_t *demux)
{
    demux_sys_t *sys = demux->p_sys;

    /* Next track */
    if (gme_track_ended (sys->emu))
    {
        msg_Dbg (demux, "track %u ended", sys->track_id);
        if (++sys->track_id >= (unsigned)gme_track_count (sys->emu))
            return 0;

        demux->info.i_update |= INPUT_UPDATE_TITLE;
        demux->info.i_title = sys->track_id;
        gme_start_track (sys->emu, sys->track_id);
    }


    block_t *block = block_Alloc (2 * 2 * SAMPLES);
    if (unlikely(block == NULL))
        return 0;

    gme_err_t ret = gme_play (sys->emu, 2 * SAMPLES, (void *)block->p_buffer);
    if (ret != NULL)
    {
        block_Release (block);
        msg_Err (demux, "%s", ret);
        return 0;
    }

    block->i_pts = block->i_dts = VLC_TS_0 + date_Get (&sys->pts);
    es_out_Control (demux->out, ES_OUT_SET_PCR, block->i_pts);
    es_out_Send (demux->out, sys->es, block);
    date_Increment (&sys->pts, SAMPLES);
    return 1;
}
예제 #2
0
/* Play some of a stream previously started with GME_play() */
int GME_playAudio(struct MUSIC_GME *music, Uint8 *stream, int len)
{
    if(music==NULL) return 1;
    if(music->game_emu==NULL) return 1;
    if(music->playing==-1) return 1;
    if( len<0 ) return 0;
    int srgArraySize = len/music->cvt.len_ratio;
    short buf[srgArraySize];
    int srcLen = (int)((double)(len/2)/music->cvt.len_ratio);

    char *err = (char*)gme_play( music->game_emu, srcLen, buf );
    if( err != NULL)
    {
        Mix_SetError("GAME-EMU: %s", err);
        return 0;
    }
    int dest_len = srcLen*2;

    if( music->cvt.needed ) {
        music->cvt.len = dest_len;
        music->cvt.buf = (Uint8*)buf;
        SDL_ConvertAudio(&music->cvt);
        dest_len = music->cvt.len_cvt;
    }

    if ( music->volume == MIX_MAX_VOLUME )
    {
        SDL_memcpy(stream, (Uint8*)buf, dest_len);
    } else {
        SDL_MixAudioFormat(stream, (Uint8*)buf, mixer.format, dest_len, music->volume);
    }
    return len-dest_len;
}
예제 #3
0
파일: GME.cpp 프로젝트: biddyweb/QMPlay2
bool GME::read(Packet &decoded, int &idx)
{
	if (m_aborted || gme_track_ended(m_gme))
		return false;

	gme_set_fade(m_gme, (m_length - 8) * 1000); //Set every time to avoid problems

	const int chunkSize = 1024 * 2; //Always stereo

	decoded.resize(chunkSize * sizeof(float));
	qint16 *srcData = (qint16 *)decoded.data();
	float *dstData = (float *)decoded.data();

	if (gme_play(m_gme, chunkSize, srcData) != NULL)
		return false;

	for (int i = chunkSize - 1; i >= 0; --i)
		dstData[i] = srcData[i] / 32768.0;

	decoded.ts = gme_tell(m_gme) / 1000.0;
	decoded.duration = chunkSize / 2 / (double)m_srate;

	idx = 0;

	return true;
}
예제 #4
0
파일: win_snd.c 프로젝트: HipsterLion/SRB2
// Callback hook to read streaming GME data.
static FMOD_RESULT F_CALLBACK GMEReadCallback(FMOD_SOUND *sound, void *data, unsigned int datalen)
{
	Music_Emu *emu;
	void *emuvoid = NULL;
	// get our emu
	FMR(FMOD_Sound_GetUserData(sound, &emuvoid));
	emu = emuvoid;
	// no emu? no play.
	if (!emu)
		return FMOD_ERR_FILE_EOF;
	if (gme_track_ended(emu))
	{
		// don't delete the primary music stream
		if (emu == gme)
			return FMOD_ERR_FILE_EOF;
		// do delete sfx streams
		FMR(FMOD_Sound_SetUserData(sound, NULL));
		gme_delete(emu);
		return FMOD_ERR_FILE_EOF;
	}
	// play beautiful musics theme of ancient land.
	if (gme_play(emu, datalen/2, data))
		return FMOD_ERR_FILE_BAD;
	// O.K
	return FMOD_OK;
}
예제 #5
0
static void
gst_gme_play (GstPad * pad)
{
  GstGmeDec *gme = GST_GME_DEC (gst_pad_get_parent (pad));
  GstFlowReturn flow_return;
  GstBuffer *out;
  gboolean seeking = gme->seeking;
  gme_err_t gme_err = NULL;
  const int NUM_SAMPLES = 1600; /* 4 bytes (stereo 16-bit) per sample */

  if (!seeking) {
    GstMapInfo map;

    out = gst_buffer_new_and_alloc (NUM_SAMPLES * 4);
    GST_BUFFER_TIMESTAMP (out) = gme_tell (gme->player) * GST_MSECOND;

    gst_buffer_map (out, &map, GST_MAP_WRITE);
    gme_err = gme_play (gme->player, NUM_SAMPLES * 2, (short *) map.data);
    gst_buffer_unmap (out, &map);

    if (gme_err) {
      GST_ELEMENT_ERROR (gme, STREAM, DEMUX, (NULL), ("%s", gme_err));
      gst_pad_pause_task (pad);
      gst_pad_push_event (pad, gst_event_new_eos ());
      gst_object_unref (gme);
      return;
    }
  } else {
    gme_seek (gme->player, gme->seekpoint);
    gme->seeking = FALSE;

    out = gst_buffer_new ();
  }

  if ((flow_return = gst_pad_push (gme->srcpad, out)) != GST_FLOW_OK) {
    GST_DEBUG_OBJECT (gme, "pausing task, reason %s",
        gst_flow_get_name (flow_return));

    gst_pad_pause_task (pad);

    if (flow_return == GST_FLOW_EOS) {
      gst_pad_push_event (pad, gst_event_new_eos ());
    } else if (flow_return < GST_FLOW_EOS || flow_return == GST_FLOW_NOT_LINKED) {
      GST_ELEMENT_ERROR (gme, STREAM, FAILED, ("Internal data stream error."),
          ("stream stopped, reason %s", gst_flow_get_name (flow_return)));

      gst_pad_push_event (pad, gst_event_new_eos ());
    }
  }

  if (gme_tell (gme->player) * GST_MSECOND > gme->total_duration) {
    gst_pad_pause_task (pad);
    gst_pad_push_event (pad, gst_event_new_eos ());
  }

  gst_object_unref (gme);

  return;
}
int crPlayerGenerateStereoFrames(void *context, int16_t *samples, int frameCount)
{
    gmeContext *gme = (gmeContext*)context;
    gme_err_t status;

    status = gme_play(gme->emu, frameCount * SAMPLES_PER_FRAME, samples);

    return (status == NULL);
}
예제 #7
0
void Music_Player::fill_buffer( void* data, sample_t* out, int count )
{
	Music_Player* self = (Music_Player*) data;
	if ( self->emu_ )
	{
		if ( gme_play( self->emu_, count, out ) ) { } // ignore error
		
		if ( self->scope_buf )
			memcpy( self->scope_buf, out, self->scope_buf_size * sizeof *self->scope_buf );
	}
}
예제 #8
0
파일: cgme.c 프로젝트: jubalh/deadbeef
static int
cgme_read (DB_fileinfo_t *_info, char *bytes, int size) {
    gme_fileinfo_t *info = (gme_fileinfo_t*)_info;
    float t = (size/4) / (float)_info->fmt.samplerate;
    if (_info->readpos + t >= info->duration) {
        t = info->duration - _info->readpos;
        if (t <= 0) {
            return 0;
        }
        // DON'T ajust size, buffer must always be po2
        //size = t * (float)info->samplerate * 4;
    }

    if (chip_voices_changed) {
        chip_voices = deadbeef->conf_get_int ("chip.voices", 0xff);
        chip_voices_changed = 0;
        gme_mute_voices (info->emu, chip_voices^0xff);
    }

    if (gme_play (info->emu, size/2, (short*)bytes)) {
        return 0;
    }
    if (conf_fadeout > 0 && info->duration >= conf_fadeout && info->reallength <= 0 && _info->readpos >= info->duration - conf_fadeout) {
        float fade_amnt =  (info->duration - _info->readpos) / (float)conf_fadeout;
        int nsamples = size/2;
        float fade_incr = 1.f / (_info->fmt.samplerate * conf_fadeout) * 256;
        const float ln10=2.3025850929940002f;
        float fade = exp(ln10*(-(1.f-fade_amnt) * 3));

        for (int i = 0; i < nsamples; i++) {
            ((short*)bytes)[i] *= fade;
            if (!(i & 0xff)) {
                fade_amnt += fade_incr;
                fade = exp(ln10*(-(1.f-fade_amnt) * 3));
            }
        }
    }

    _info->readpos += t;
    if (info->reallength == -1) {
        if (gme_track_ended (info->emu)) {
            return 0;
        }
    }
    return size;
}
예제 #9
0
파일: snes.c 프로젝트: Sahasrara/Subtle
/**
 * NOT USED
 */
void
Java_com_example_subtle_SoundMachine_convertToWave( JNIEnv* env, jobject callingObject, jstring fromPath, jstring toPath )
{
	/* Buffer Size */
	int buf_size = 1024; /* can be any multiple of 2 */

	/* Grab Paths */
	const char *from_path = (*env)->GetStringUTFChars(env, fromPath, 0);
	const char *to_path = (*env)->GetStringUTFChars(env, toPath, 0);

	/* Open music file in new emulator */
	Music_Emu* emu;
	handle_error( gme_open_file( from_path, &emu, SAMPLE_RATE ) );

	/* Get Track Info */
	gme_info_t* track_info = NULL;
	handle_error( gme_track_info( emu, &track_info, TRACK ) );

	/* Start track */
	handle_error( gme_start_track( emu, TRACK ) );

	/* Begin writing to wave file */
	wave_open( SAMPLE_RATE, to_path );
	wave_enable_stereo();

	/* Output to Wave */
	while ( gme_tell( emu ) < track_info->play_length )
	{
		/* Sample buffer */
		short buf [buf_size];

		/* Fill sample buffer */
		handle_error( gme_play( emu, buf_size, buf ) );

		/* Write samples to wave file */
		wave_write( buf, buf_size );
	}

	/* Cleanup */
	gme_free_info( track_info );
	(*env)->ReleaseStringUTFChars(env, fromPath, from_path);
	(*env)->ReleaseStringUTFChars(env, toPath, to_path);
	gme_delete( emu );
	wave_close();
}
예제 #10
0
jint Java_de_illogical_modo_GmeDecoder_gmeGetSamples(JNIEnv* env, jclass clazz, jshortArray samples)
{
    if (emu == NULL)
    {
        return -1;
    }

    // How many samples are needed
    int sampleCount = (*env)->GetArrayLength(env, samples);

    // Fill in local playback, no more than 50k, returns NULL on success
    gme_err_t err = gme_play(emu, sampleCount, localSamples);

    // copy local buffer to java array
    (*env)->SetShortArrayRegion(env, samples, 0, sampleCount, localSamples);

    return err == NULL;
}
예제 #11
0
파일: libgme.c 프로젝트: DeHackEd/FFmpeg
static int read_packet_gme(AVFormatContext *s, AVPacket *pkt)
{
    GMEContext *gme = s->priv_data;
    int n_samples = AUDIO_PKT_SIZE / 2;
    int ret;

    if (gme_track_ended(gme->music_emu))
        return AVERROR_EOF;

    if ((ret = av_new_packet(pkt, AUDIO_PKT_SIZE)) < 0)
        return ret;

    if (gme_play(gme->music_emu, n_samples, (short *)pkt->data))
        return AVERROR_EXTERNAL;
    pkt->size = AUDIO_PKT_SIZE;

    return 0;
}
예제 #12
0
int GmeDecoder::decode()
{
	short *sbuf = static_cast<short*>(buffer);
	int size = bufferSize / sizeof(short);

	if (gme_play(emu, size, sbuf) != 0)
		throw love::Exception("Error while decoding game music");

	if (!eof && gme_track_ended(emu))
	{
		// Start the next track if this one ended.
		if (cur_track < num_tracks - 1)
			gme_start_track(emu, ++cur_track);
		else
			eof = true;
	}

	return bufferSize;
}
예제 #13
0
JNIEXPORT jint JNICALL Java_com_ssb_droidsound_plugins_GMEPlugin_N_1getSoundData(JNIEnv *env, jobject obj, jlong song, jshortArray bArray, int size)
{
	GMEInfo *info = (GMEInfo*)song;

	if(!info->started) {
		gme_err_t err = gme_start_track(info->emu, 0);
		info->started = true;
	}

	if(gme_track_ended(info->emu)) {
		return 0;
	}

	jshort *ptr = env->GetShortArrayElements(bArray, NULL);
	//__android_log_print(ANDROID_LOG_VERBOSE, "GMEPlugin", "Getting %d shorts from %p", size, emu);
	gme_err_t err = gme_play(info->emu, size, ptr);
	//__android_log_print(ANDROID_LOG_VERBOSE, "GMEPlugin", "Result %d", err);
	env->ReleaseShortArrayElements(bArray, ptr, 0);
	return size;
}
예제 #14
0
JNIEXPORT jint JNICALL Java_com_ssb_droidsound_plugins_GMEPlugin_N_1getSoundData(JNIEnv *env, jobject obj, jlong song, jshortArray sArray, int size)
{
	GMEInfo *info = (GMEInfo*)song;

	if(!info->started) {
		gme_err_t err = gme_start_track(info->emu, 0);
		info->started = true;
	}

	if(gme_track_ended(info->emu)) {
		return -1;
	}

	jshort *ptr = env->GetShortArrayElements(sArray, NULL);

	gme_err_t err = gme_play(info->emu, size, ptr);

	env->ReleaseShortArrayElements(sArray, ptr, 0);
	return size;
}
예제 #15
0
파일: basics.c 프로젝트: STJr/SRB2
int main(int argc, char *argv[])
{
	const char *filename = "test.nsf"; /* Default file to open */
	if ( argc >= 2 )
		filename = argv[1];

	long sample_rate = 44100; /* number of samples per second */
	/* index of track to play (0 = first) */
	int track = argc >= 3 ? atoi(argv[2]) : 0;
	
	/* Open music file in new emulator */
	Music_Emu* emu;
	handle_error( gme_open_file( filename, &emu, sample_rate ) );
	
	/* Start track */
	handle_error( gme_start_track( emu, track ) );
	
	/* Begin writing to wave file */
	wave_open( sample_rate, "out.wav" );
	wave_enable_stereo();
	
	/* Record 10 seconds of track */
	while ( gme_tell( emu ) < 10 * 1000L )
	{
		/* Sample buffer */
		#define buf_size 1024 /* can be any multiple of 2 */
		short buf [buf_size];
		
		/* Fill sample buffer */
		handle_error( gme_play( emu, buf_size, buf ) );
		
		/* Write samples to wave file */
		wave_write( buf, buf_size );
	}
	
	/* Cleanup */
	gme_delete( emu );
	wave_close();
	
	return 0;
}
예제 #16
0
static int
cgme_read (DB_fileinfo_t *_info, char *bytes, int size) {
    gme_fileinfo_t *info = (gme_fileinfo_t*)_info;
    int playForever = conf_play_forever && info->can_loop;
    float t = (size/4) / (float)_info->fmt.samplerate;
    if (info->eof) {
        return 0;
    }
    if (!playForever && _info->readpos + t >= info->duration) {
        t = info->duration - _info->readpos;
        if (t <= 0) {
            return 0;
        }
        // DON'T ajust size, buffer must always be po2
        //size = t * (float)info->samplerate * 4;
    }

    if (chip_voices_changed) {
        chip_voices = deadbeef->conf_get_int ("chip.voices", 0xff);
        chip_voices_changed = 0;
        gme_mute_voices (info->emu, chip_voices^0xff);
    }

    if (playForever)
        gme_set_fade(info->emu, -1, 0);
    else
        gme_set_fade(info->emu, (int)(info->duration * 1000), conf_fadeout * 1000);

    if (gme_play (info->emu, size/2, (short*)bytes)) {
        return 0;
    }

    _info->readpos += t;
    if (gme_track_ended (info->emu)) {
        info->eof = 1;
    }
    return size;
}
예제 #17
0
/* Read some data */
static gint
xmms_gme_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len, xmms_error_t *err)
{
	xmms_gme_data_t *data;
	gme_err_t play_error;

	g_return_val_if_fail (xform, -1);

	data = (xmms_gme_data_t *)xmms_xform_private_data_get (xform);
	g_return_val_if_fail (data, -1);

	if (gme_track_ended (data->emu))
		return 0;

	play_error = gme_play (data->emu, len/2, (short int *)buf);
	if (play_error) {
		XMMS_DBG ("gme_play returned an error: %s", play_error);
		xmms_error_set (err, XMMS_ERROR_GENERIC, play_error);
		return -1;
	}

	return len;
}
예제 #18
0
파일: glue.cpp 프로젝트: Chaduke/bah.mod
BBString * bmx_gme_play(MaxMusicEmu * emu, long count, short * out) {
	return bbStringFromCString(gme_play(emu->emu, count, out));
}
예제 #19
0
static event_t *
fa_gme_playfile_internal(media_pipe_t *mp, void *fh,
			 char *errbuf, size_t errlen, int hold, int track)
{
  media_queue_t *mq = &mp->mp_audio;
  Music_Emu *emu;
  gme_err_t err;
  char *buf;
  int lost_focus = 0;
  size_t size, r;
  int sample_rate = 48000;
  media_buf_t *mb = NULL;
  event_t *e;

  size = fa_fsize(fh);

  buf = malloc(size);
  r = fa_read(fh, buf, size);

  if(r != size) {
    snprintf(errbuf, errlen, "Unable to read file");
    free(buf);
    return NULL;
  }

  err = gme_open_data(buf, size, &emu, sample_rate);
  free(buf);
  if(err != NULL) {
    snprintf(errbuf, errlen, "Unable to load file -- %s", err);
    return NULL;
  }

  gme_start_track(emu, track);

  mp_set_playstatus_by_hold(mp, hold, NULL);
  mp->mp_audio.mq_stream = 0;
  mp_set_play_caps(mp, MP_PLAY_CAPS_PAUSE | MP_PLAY_CAPS_SEEK);
  mp_become_primary(mp);
  

  while(1) {

    if(gme_track_ended(emu)) {
      e = event_create_type(EVENT_EOF);
      break;
    }

    if(mb == NULL) {
      mb = media_buf_alloc();
      mb->mb_data_type = MB_AUDIO;
      mb->mb_channels = 2;
      mb->mb_size = sizeof(int16_t) * CHUNK_SIZE * mb->mb_channels;
      mb->mb_data = malloc(mb->mb_size);
      mb->mb_rate = sample_rate;
      mb->mb_time = gme_tell(emu) * 1000;
      gme_play(emu, CHUNK_SIZE * mb->mb_channels, mb->mb_data);
    }

    if((e = mb_enqueue_with_events(mp, mq, mb)) == NULL) {
      mb = NULL; /* Enqueue succeeded */
      continue;
    }
    if(event_is_type(e, EVENT_PLAYQUEUE_JUMP)) {
      mp_flush(mp, 0);
      break;


    } else if(event_is_type(e, EVENT_SEEK)) {

      event_ts_t *ets = (event_ts_t *)e;
      gme_seek(emu, ets->pts / 1000);
      seekflush(mp, &mb);
      
    } else if(event_is_action(e, ACTION_SEEK_FAST_BACKWARD)) {

      deltaseek(mp, &mb, emu, -60000);

    } else if(event_is_action(e, ACTION_SEEK_BACKWARD)) {

      deltaseek(mp, &mb, emu, -15000);

    } else if(event_is_action(e, ACTION_SEEK_FAST_FORWARD)) {

      deltaseek(mp, &mb, emu, 60000);

    } else if(event_is_action(e, ACTION_SEEK_FORWARD)) {

      deltaseek(mp, &mb, emu, 15000);

    } else if(event_is_action(e, ACTION_PLAYPAUSE) ||
	      event_is_action(e, ACTION_PLAY) ||
	      event_is_action(e, ACTION_PAUSE)) {

      hold = action_update_hold_by_event(hold, e);
      mp_send_cmd_head(mp, mq, hold ? MB_CTRL_PAUSE : MB_CTRL_PLAY);
      lost_focus = 0;
      mp_set_playstatus_by_hold(mp, hold, NULL);

    } else if(event_is_type(e, EVENT_MP_NO_LONGER_PRIMARY)) {

      hold = 1;
      lost_focus = 1;
      mp_send_cmd_head(mp, mq, MB_CTRL_PAUSE);
      mp_set_playstatus_by_hold(mp, hold, e->e_payload);

    } else if(event_is_type(e, EVENT_MP_IS_PRIMARY)) {

      if(lost_focus) {
	hold = 0;
	lost_focus = 0;
	mp_send_cmd_head(mp, mq, MB_CTRL_PLAY);
	mp_set_playstatus_by_hold(mp, hold, NULL);
      }

    } else if(event_is_type(e, EVENT_INTERNAL_PAUSE)) {

      hold = 1;
      lost_focus = 0;
      mp_send_cmd_head(mp, mq, MB_CTRL_PAUSE);
      mp_set_playstatus_by_hold(mp, hold, e->e_payload);

    } else if(event_is_action(e, ACTION_PREV_TRACK) ||
	      event_is_action(e, ACTION_NEXT_TRACK) ||
	      event_is_action(e, ACTION_STOP)) {
      mp_flush(mp, 0);
      break;
    }
    event_release(e);
  }  

  gme_delete(emu);

  if(mb != NULL)
    media_buf_free(mb);

  if(hold) { 
    // If we were paused, release playback again.
    mp_send_cmd(mp, mq, MB_CTRL_PLAY);
    mp_set_playstatus_by_hold(mp, 0, NULL);
  }
  return e;
}
예제 #20
0
static event_t *
fa_gme_playfile_internal(media_pipe_t *mp, const void *buf, size_t size,
			 char *errbuf, size_t errlen, int hold, int track,
			 const char *url)
{
  media_queue_t *mq = &mp->mp_audio;
  Music_Emu *emu;
  gme_err_t err;
  int sample_rate = 48000;
  media_buf_t *mb = NULL;
  event_t *e;
  int registered_play = 0;

  err = gme_open_data(buf, size, &emu, sample_rate);
  if(err != NULL) {
    snprintf(errbuf, errlen, "Unable to load file -- %s", err);
    return NULL;
  }

  gme_start_track(emu, track);

  mp->mp_audio.mq_stream = 0;
  mp_configure(mp, MP_PLAY_CAPS_PAUSE | MP_PLAY_CAPS_SEEK,
	       MP_BUFFER_SHALLOW, 0);
  mp_become_primary(mp);
  

  while(1) {

    if(gme_track_ended(emu)) {
      e = event_create_type(EVENT_EOF);
      break;
    }

    if(mb == NULL) {
      mb = media_buf_alloc_unlocked(mp, sizeof(int16_t) * CHUNK_SIZE * 2);
      mb->mb_data_type = MB_AUDIO;
      mb->mb_channels = 2;
      mb->mb_rate = sample_rate;
      mb->mb_pts = gme_tell(emu) * 1000;
      mb->mb_drive_clock = 1;

      if(!registered_play && mb->mb_pts > METADB_AUDIO_PLAY_THRESHOLD) {
	registered_play = 1;
	metadb_register_play(url, 1, CONTENT_AUDIO);
      }

      gme_play(emu, CHUNK_SIZE * mb->mb_channels, mb->mb_data);
    }

    if((e = mb_enqueue_with_events(mp, mq, mb)) == NULL) {
      mb = NULL; /* Enqueue succeeded */
      continue;
    }
    if(event_is_type(e, EVENT_PLAYQUEUE_JUMP)) {
      mp_flush(mp, 0);
      break;


    } else if(event_is_type(e, EVENT_SEEK)) {

      event_ts_t *ets = (event_ts_t *)e;
      gme_seek(emu, ets->ts / 1000);
      seekflush(mp, &mb);
      
    } else if(event_is_action(e, ACTION_SKIP_BACKWARD) ||
	      event_is_action(e, ACTION_SKIP_FORWARD) ||
	      event_is_action(e, ACTION_STOP)) {
      mp_flush(mp, 0);
      break;
    }
    event_release(e);
  }  

  gme_delete(emu);

  if(mb != NULL)
    media_buf_free_unlocked(mp, mb);

  return e;
}
예제 #21
0
파일: snes.c 프로젝트: Sahasrara/Subtle
void
Java_com_example_subtle_SoundMachine_fillBuffer( JNIEnv* env, jobject callingObject, jstring filePath, jshortArray bufferArray, jint myID )
{
	/* Grab File Path */
	const char *file_path = (*env)->GetStringUTFChars(env, filePath, 0);

	/* Get Class Information */
	jclass thisClass = (*env)->GetObjectClass(env, callingObject);

	/* Open music file in new emulator */
	Music_Emu* emu;
	handle_error( gme_open_file( file_path, &emu, SAMPLE_RATE ) );

	/* Get Track Info */
	gme_info_t* track_info = NULL;
	handle_error( gme_track_info( emu, &track_info, TRACK ) );

	/* Start track */
	handle_error( gme_start_track( emu, TRACK ) );

	/* Start Filling Buffer */
	jshort current_state = 0;
	jfieldID fid_playback_command = (*env)->GetFieldID(env, thisClass, "JNIPlaybackCommand", "I");
	jfieldID fid_active_thread = (*env)->GetFieldID(env, thisClass, "activeThreadID", "I");
	jfieldID fid_seek_to = (*env)->GetFieldID(env, thisClass, "seekTo", "I");
	jmethodID mid_write = (*env)->GetMethodID(env, thisClass, "fillBufferCallback", "(I)V");
	jsize buffer_size = (*env)->GetArrayLength( env, bufferArray );
	jshort *buffer_pointer;
	jint command;
	jint currentPosition;
	jint activeID;
	jint seekTo;
	while ( 1 )
	{
		/**
		 * Read Control Commands
		 */
		/* Get Control Command */
		command = (*env)->GetIntField(env, callingObject, fid_playback_command);

		/* Get Active Thread ID */
		activeID = (*env)->GetIntField(env, callingObject, fid_active_thread);

		/* Get Seek To */
		seekTo = (*env)->GetIntField(env, callingObject, fid_seek_to);

		/**
		 * Respond to Control Commands
		 */
		if ( activeID != myID || command == SIG_STOP ) { // stop or new track is now playing
			/* Exit */
			break;
		} else if (seekTo != SEEK_STATUS_NOT_SEEKING) {
			/* Seek */
			handle_error( gme_seek ( emu, seekTo ) );

			/* Report Seek */
			(*env)->CallVoidMethod(env, callingObject, mid_write, SEEK_STATUS_FINISHED_SEEKING);
		} else if ( command == SIG_PLAY ) {
			/* If We Finish, Kill Thread */
			if (gme_tell( emu ) >= track_info->play_length) {
				/* Write Buffer */
				(*env)->CallVoidMethod(env, callingObject, mid_write, track_info->play_length); // Finished Track

				/* Exit */
				break;
			}

			/* Get Java Buffer */
			buffer_pointer = (*env)->GetShortArrayElements( env, bufferArray, NULL );

			/* Fill sample buffer */
			handle_error( gme_play( emu, buffer_size, buffer_pointer ) );

			/* Release Java Buffer */
			(*env)->ReleaseShortArrayElements( env, bufferArray, buffer_pointer, 0 );

			/* Get Current Position */
			currentPosition = gme_tell( emu );

			/* Write Buffer */
			(*env)->CallVoidMethod(env, callingObject, mid_write, currentPosition);
		} else if ( command == SIG_PAUSE ) {
			/* Get Current Position */
			currentPosition = gme_tell( emu );

			/* Write Buffer */
			(*env)->CallVoidMethod(env, callingObject, mid_write, currentPosition);

			/* Sleep */
			sleep(.1);
		}
	}

	/* Cleanup */
	(*env)->ReleaseStringUTFChars(env, filePath, file_path);
	gme_free_info( track_info );
	gme_delete( emu );
}