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; }
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; }
jlong Java_de_illogical_modo_GmeDecoder_gmeSeek(JNIEnv* env, jclass clazz, jlong milli) { if (emu == NULL) { return -1; } return gme_seek(emu, gme_tell(emu) + milli) == NULL; }
jlong Java_de_illogical_modo_GmeDecoder_gmePlaytime(JNIEnv* env, jclass clazz) { if (emu == NULL) { return -1; } return gme_tell(emu); }
static void deltaseek(media_pipe_t *mp, media_buf_t **mbp, Music_Emu *emu, int delta) { int pos = gme_tell(emu) + delta; if(pos < 0) pos = 0; gme_seek(emu, pos); seekflush(mp, mbp); }
/** * 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(); }
FString GMESong::GetStats() { FString out; if (TrackInfo != NULL) { int time = gme_tell(Emu); out.Format( "Track: " TEXTCOLOR_YELLOW "%d" TEXTCOLOR_NORMAL " Time:" TEXTCOLOR_YELLOW "%3d:%02d:%03d" TEXTCOLOR_NORMAL " System: " TEXTCOLOR_YELLOW "%s" TEXTCOLOR_NORMAL, CurrTrack, time/60000, (time/1000) % 60, time % 1000, TrackInfo->system); } return out; }
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; }
static gboolean gst_gme_dec_src_query (GstPad * pad, GstObject * parent, GstQuery * query) { GstGmeDec *gme = GST_GME_DEC (parent); gboolean result = TRUE; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_DURATION: { GstFormat format; gst_query_parse_duration (query, &format, NULL); if (!gme->initialized || format != GST_FORMAT_TIME || gme->total_duration == GST_CLOCK_TIME_NONE) { result = FALSE; break; } gst_query_set_duration (query, GST_FORMAT_TIME, gme->total_duration); break; } case GST_QUERY_POSITION: { GstFormat format; gst_query_parse_position (query, &format, NULL); if (!gme->initialized || format != GST_FORMAT_TIME) { result = FALSE; break; } gst_query_set_position (query, GST_FORMAT_TIME, (gint64) gme_tell (gme->player) * GST_MSECOND); break; } default: result = gst_pad_query_default (pad, parent, query); break; } return result; }
static gint64 xmms_gme_seek (xmms_xform_t *xform, gint64 samples, xmms_xform_seek_mode_t whence, xmms_error_t *err) { xmms_gme_data_t *data; gint64 target_time; gint duration; int samplerate; g_return_val_if_fail (whence == XMMS_XFORM_SEEK_SET, -1); 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); samplerate = data->samplerate; if (samples < 0) { xmms_error_set (err, XMMS_ERROR_INVAL, "Trying to seek before start of stream"); return -1; } target_time = (samples / samplerate) * 1000; xmms_xform_metadata_get_int (xform, XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION, &duration); if (target_time > duration) { xmms_error_set (err, XMMS_ERROR_INVAL, "Trying to seek past end of stream"); return -1; } gme_seek (data->emu, target_time); return (gme_tell (data->emu) / 1000) * samplerate; }
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; }
static int Control (demux_t *demux, int query, va_list args) { demux_sys_t *sys = demux->p_sys; switch (query) { case DEMUX_CAN_SEEK: *va_arg (args, bool *) = true; return VLC_SUCCESS; case DEMUX_GET_POSITION: { double *pos = va_arg (args, double *); if (unlikely(sys->track_id >= sys->titlec) || (sys->titlev[sys->track_id]->i_length == 0)) *pos = 0.; else { int offset = gme_tell (sys->emu); *pos = (double)offset / (double)(sys->titlev[sys->track_id]->i_length / 1000); } return VLC_SUCCESS; } case DEMUX_SET_POSITION: { double pos = va_arg (args, double); if (unlikely(sys->track_id >= sys->titlec) || (sys->titlev[sys->track_id]->i_length == 0)) break; int seek = (sys->titlev[sys->track_id]->i_length / 1000) * pos; if (gme_seek (sys->emu, seek)) break; return VLC_SUCCESS; } case DEMUX_GET_LENGTH: { int64_t *v = va_arg (args, int64_t *); if (unlikely(sys->track_id >= sys->titlec) || (sys->titlev[sys->track_id]->i_length == 0)) break; *v = sys->titlev[sys->track_id]->i_length; return VLC_SUCCESS; } case DEMUX_GET_TIME: { int64_t *v = va_arg (args, int64_t *); *v = gme_tell (sys->emu) * INT64_C(1000); return VLC_SUCCESS; } case DEMUX_SET_TIME: { int64_t v = va_arg (args, int64_t) / 1000; if (v > INT_MAX || gme_seek (sys->emu, v)) break; return VLC_SUCCESS; } case DEMUX_GET_TITLE_INFO: { input_title_t ***titlev = va_arg (args, input_title_t ***); int *titlec = va_arg (args, int *); *(va_arg (args, int *)) = 0; /* Title offset */ *(va_arg (args, int *)) = 0; /* Chapter offset */ unsigned n = sys->titlec; *titlev = malloc (sizeof (**titlev) * n); if (unlikely(*titlev == NULL)) n = 0; *titlec = n; for (unsigned i = 0; i < n; i++) (*titlev)[i] = vlc_input_title_Duplicate (sys->titlev[i]); return VLC_SUCCESS; } case DEMUX_SET_TITLE: { int track_id = va_arg (args, int); if (track_id >= gme_track_count (sys->emu)) break; gme_start_track (sys->emu, track_id); demux->info.i_update |= INPUT_UPDATE_TITLE; demux->info.i_title = track_id; sys->track_id = track_id; return VLC_SUCCESS; } } return VLC_EGENERIC; }
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 ); }
static gboolean gst_gme_dec_src_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstGmeDec *gme = GST_GME_DEC (parent); gboolean result = FALSE; switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEEK: { gdouble rate; GstFormat format; GstSeekFlags flags; GstSeekType start_type, stop_type; gint64 start, stop; gboolean flush; gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start, &stop_type, &stop); gst_event_unref (event); if (format != GST_FORMAT_TIME) { GST_DEBUG_OBJECT (gme, "seeking is only supported in TIME format"); break; } if (start_type != GST_SEEK_TYPE_SET || stop_type != GST_SEEK_TYPE_NONE) { GST_DEBUG_OBJECT (gme, "unsupported seek type"); break; } if (stop_type == GST_SEEK_TYPE_NONE) stop = GST_CLOCK_TIME_NONE; if (start_type == GST_SEEK_TYPE_SET) { GstSegment seg; guint64 cur = gme_tell (gme->player) * GST_MSECOND; guint64 dest = (guint64) start; if (gme->total_duration != GST_CLOCK_TIME_NONE) dest = CLAMP (dest, 0, gme->total_duration); else dest = MAX (0, dest); if (dest == cur) break; flush = (flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH; if (flush) { gst_pad_push_event (gme->srcpad, gst_event_new_flush_start ()); } else { gst_pad_stop_task (gme->srcpad); } GST_PAD_STREAM_LOCK (gme->srcpad); if (flags & GST_SEEK_FLAG_SEGMENT) { gst_element_post_message (GST_ELEMENT (gme), gst_message_new_segment_start (GST_OBJECT (gme), format, cur)); } if (flush) { gst_pad_push_event (gme->srcpad, gst_event_new_flush_stop (TRUE)); } if (stop == GST_CLOCK_TIME_NONE && gme->total_duration != GST_CLOCK_TIME_NONE) stop = gme->total_duration; gst_segment_init (&seg, GST_FORMAT_TIME); seg.rate = rate; seg.start = dest; seg.stop = stop; seg.time = dest; gst_pad_push_event (gme->srcpad, gst_event_new_segment (&seg)); gme->seekpoint = dest / GST_MSECOND; /* nsecs to msecs */ gme->seeking = TRUE; gst_pad_start_task (gme->srcpad, (GstTaskFunction) gst_gme_play, gme->srcpad, NULL); GST_PAD_STREAM_UNLOCK (gme->srcpad); result = TRUE; } break; } default: result = gst_pad_push_event (gme->sinkpad, event); break; } return result; }
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; }
long bmx_gme_tell(MaxMusicEmu * emu) { return gme_tell(emu->emu); }