static void spc_play (GstPad * pad) { GstSpcDec *spc = GST_SPC_DEC (gst_pad_get_parent (pad)); GstFlowReturn flow_return; GstBuffer *out; gboolean seeking = spc->seeking; gint64 duration, fade, end, position; if (!seeking) { out = gst_buffer_new_and_alloc (1600 * 4); gst_buffer_set_caps (out, GST_PAD_CAPS (pad)); GST_BUFFER_TIMESTAMP (out) = (gint64) gst_util_uint64_scale ((guint64) spc->byte_pos, GST_SECOND, 32000 * 2 * 2); spc->byte_pos += OSPC_Run (-1, (short *) GST_BUFFER_DATA (out), 1600 * 4); } else { if (spc->seekpoint < spc->byte_pos) { OSPC_Init (GST_BUFFER_DATA (spc->buf), GST_BUFFER_SIZE (spc->buf)); spc->byte_pos = 0; } spc->byte_pos += OSPC_Run (-1, NULL, 1600 * 4); if (spc->byte_pos >= spc->seekpoint) { spc->seeking = FALSE; } out = gst_buffer_new (); gst_buffer_set_caps (out, GST_PAD_CAPS (pad)); } duration = gst_spc_duration (spc); fade = gst_spc_fadeout (spc); end = duration + fade; position = (gint64) gst_util_uint64_scale ((guint64) spc->byte_pos, GST_SECOND, 32000 * 2 * 2); if (position >= duration) { gint16 *data = (gint16 *) GST_BUFFER_DATA (out); guint32 size = GST_BUFFER_SIZE (out) / sizeof (gint16); unsigned int i; gint64 num = (fade - (position - duration)); for (i = 0; i < size; i++) { /* Apply a parabolic volume envelope */ data[i] = (gint16) (data[i] * num / fade * num / fade); } } if ((flow_return = gst_pad_push (spc->srcpad, out)) != GST_FLOW_OK) { GST_DEBUG_OBJECT (spc, "pausing task, reason %s", gst_flow_get_name (flow_return)); gst_pad_pause_task (pad); if (GST_FLOW_IS_FATAL (flow_return) || flow_return == GST_FLOW_NOT_LINKED) { gst_pad_push_event (pad, gst_event_new_eos ()); } } if (position >= end) { gst_pad_pause_task (pad); gst_pad_push_event (pad, gst_event_new_eos ()); } gst_object_unref (spc); return; }
static event_t * openspc_play(media_pipe_t *mp, AVIOContext *avio, char *errbuf, size_t errlen) { media_queue_t *mq = &mp->mp_audio; #error fa_fsize can return -1 .. deal with it size_t r, siz = fa_fsize(fh); uint8_t *buf = malloc(siz); media_buf_t *mb = NULL; event_t *e; int hold = 0, lost_focus = 0; int sample = 0; unsigned int duration = INT32_MAX; mp_set_playstatus_by_hold(mp, hold, NULL); mp->mp_audio.mq_stream = 0; fa_seek(fh, 0, SEEK_SET); r = fa_read(fh, buf, siz); fa_close(fh); if(r != siz) { free(buf); snprintf(errbuf, errlen, "openspc: Unable to read file"); return NULL; } if(OSPC_Init(buf, siz)) { free(buf); snprintf(errbuf, errlen, "openspc: Unable to initialize file"); return NULL; } if(!memcmp("v0.30", buf + 0x1c, 4) && buf[0x23] == 0x1a) { char str[4]; memcpy(str, buf + 0xa9, 3); str[3] = 0; duration = atoi(str) * 32000; } mp_set_play_caps(mp, MP_PLAY_CAPS_PAUSE); mp_become_primary(mp); while(1) { if(mb == NULL) { if(sample > duration) { while((e = mp_wait_for_empty_queues(mp, 0)) != NULL) { if(event_is_type(e, EVENT_PLAYQUEUE_JUMP) || 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); } if(e == NULL) e = event_create_type(EVENT_EOF); break; } mb = media_buf_alloc(); mb->mb_data_type = MB_AUDIO; mb->mb_size = sizeof(int16_t) * 2048 * 2; mb->mb_data = malloc(mb->mb_size); mb->mb_size = OSPC_Run(-1, mb->mb_data, mb->mb_size); mb->mb_channels = 2; mb->mb_rate = 32000; mb->mb_time = sample * 1000000LL / mb->mb_rate; sample += 2048; } 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_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); } free(buf); return e; }
int main(int argc, char *argv[]) { int optionoffset=0,audio_fd,channels=2,rformat,rchannels,format=AFMT_S16_LE,speed=32000,fd; char audio_device[]="/dev/dsp"; char ver[]="0.2"; char c; void *ptr,*buf; off_t size; if((argc<2)) { printf("\n[?] Usage: soap [sound device] SPC_FILE_NAME\n[?] Optional parameters are in brackets.\n[?] SOAP Version %s (2003) Steve B Melvin Jr\n\n",ver); exit(1); } if((argc>2)) { strcpy(audio_device,argv[1]); optionoffset++; } if((audio_fd=open(audio_device, O_WRONLY, 0)) ==-1) { printf("[-] Could not open, %s.\n", audio_device); exit(1); } printf("[+] Successfully opened, %s.\n",audio_device); rformat=format; if(ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format) == -1) { printf("[-] Could not set sound format.\n"); exit(1); } if(format!=rformat) { printf("[-] Could not set sound format.\n"); exit(1); } printf("[+] Successfully set sound format.\n"); rchannels=channels; if(ioctl(audio_fd,SNDCTL_DSP_CHANNELS, &channels) == -1) { printf("[-] Could not set channels.\n"); exit(1); } if(channels!=rchannels) { printf("[-] Could not set channels.\n"); exit(1); } printf("[+] Successfully set channels.\n"); if(ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed)==-1) { printf("[-] Could not set speed.\n"); exit(1); } printf("[+] Using speed, {%iHz}\n",speed); buf=malloc(32000); fd=open(argv[1+optionoffset],O_RDONLY); if(fd<0) { printf("[-] Could not open \'%s\'\n.",argv[1]); exit(1); } size=lseek(fd,0,SEEK_END); lseek(fd,0,SEEK_SET); ptr=malloc(size); read(fd,ptr,size); close(fd); fd=OSPC_Init(ptr,size); free(ptr); fcntl(STDIN_FILENO,F_SETFL,O_NONBLOCK); printf("[+] Playing SPC, press Enter to quit.\n"); while((read(STDIN_FILENO,&c,1))<=0) { size=OSPC_Run(-1,buf,32000); write(audio_fd,buf,size); } printf("\nGoodbye!\n"); return 0; }