Ejemplo n.º 1
0
 long __declspec(dllexport) DLL_FillBuffer(void* nsf, char* buffer, int size)
 {
   nsf_t* pNsf = (nsf_t*)nsf;
   nsf_frame(pNsf);
   pNsf->process(buffer,size);
   return size*2;
 }
Ejemplo n.º 2
0
static void nsf_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {

  nsf_decoder_t *this = (nsf_decoder_t *) this_gen;
  audio_buffer_t *audio_buffer;

  if (buf->decoder_flags & BUF_FLAG_HEADER) {

    /* When the engine sends a BUF_FLAG_HEADER flag, it is time to initialize
     * the decoder. The buffer element type has 4 decoder_info fields,
     * 0..3. Field 1 is the sample rate. Field 2 is the bits/sample. Field
     * 3 is the number of channels. */
    this->sample_rate = buf->decoder_info[1];
    this->bits_per_sample = buf->decoder_info[2];
    this->channels = buf->decoder_info[3];

    /* take this opportunity to initialize stream/meta information */
    this->stream->meta_info[XINE_META_INFO_AUDIOCODEC] = strdup("NES Music (Nosefart)");

    this->song_number = buf->content[4];
    /* allocate a buffer for the file */
    this->nsf_size = BE_32(&buf->content[0]);
    this->nsf_file = xine_xmalloc(this->nsf_size);
    this->nsf_index = 0;

    /* peform any other required initialization */
    this->last_pts = -1;
    this->iteration = 0;

    return;
  }

  /* accumulate chunks from the NSF file until whole file is received */
  if (this->nsf_index < this->nsf_size) {
    xine_fast_memcpy(&this->nsf_file[this->nsf_index], buf->content,
      buf->size);
    this->nsf_index += buf->size;

    if (this->nsf_index == this->nsf_size) {
      /* file has been received, proceed to initialize engine */
      nsf_init();
      this->nsf = nsf_load(NULL, this->nsf_file, this->nsf_size);
      if (!this->nsf) {
        printf ("nsf: could not initialize NSF\n");
        /* make the decoder return on every subsequent buffer */
        this->nsf_index = 0;
      }
      this->nsf->current_song = this->song_number;
      nsf_playtrack(this->nsf, this->nsf->current_song, this->sample_rate,
        this->bits_per_sample, this->channels);
    }
    return;
  }

  /* if the audio output is not open yet, open the audio output */
  if (!this->output_open) {
    this->output_open = this->stream->audio_out->open(
      this->stream->audio_out,
      this->stream,
      this->bits_per_sample,
      this->sample_rate,
      (this->channels == 2) ? AO_CAP_MODE_STEREO : AO_CAP_MODE_MONO);
  }

  /* if the audio still isn't open, do not go any further with the decode */
  if (!this->output_open)
    return;

  /* check if a song change was requested */
  if (buf->decoder_info[1]) {
    this->nsf->current_song = buf->decoder_info[1];
    nsf_playtrack(this->nsf, this->nsf->current_song, this->sample_rate,
      this->bits_per_sample, this->channels);
  }

  /* time to decode a frame */
  if (this->last_pts != -1) {

    /* process a frame */
    nsf_frame(this->nsf);

    /* get an audio buffer */
    audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out);
    if (audio_buffer->mem_size == 0) {
       printf ("nsf: Help! Allocated audio buffer with nothing in it!\n");
       return;
    }

    apu_process(audio_buffer->mem, this->sample_rate / this->nsf->playback_rate);
    audio_buffer->vpts = buf->pts;
    audio_buffer->num_frames = this->sample_rate / this->nsf->playback_rate;
    this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream);
  }
  this->last_pts = buf->pts;
}
Ejemplo n.º 3
0
static void * play_loop(void *arg)
{
  nsf_t * nsf = app.nsf;

  pdebug("nsf : play-thread\n");

  if (!app.nsf) {
    going = FALSE;
  }
  pdebug("nsf : going [%s]\n", going ? "Yes" : "No");

  app.cur_track = 0;
  nsf->cur_frame = nsf->cur_frame_end = 0;
  while (going) {
    if (nsf->cur_frame >= nsf->cur_frame_end) {
      int next_track = app.cur_track+1;
      pdebug("nsf : frame elapsed [%u > %u] -> track #%02d\n",
	     nsf->cur_frame,nsf->cur_frame_end, next_track);
      
      if (next_track > app.n_tracks) {
	pdebug("nsf : reach last song\n");
	going = FALSE;
	break;
      }
      SetChangeTrack(next_track, -1);
    }
    
    if (ApplyChangeTrack() < 0) {
      going = FALSE;
      break;
    }
    
    if (!app.bufcnt) {
      /* Run a frame. */
      nsf_frame(nsf);
      apu_process(app.buffer, app.buflen);
      app.bufptr = app.buffer;
      app.bufcnt = app.buflen;
    }

    if (going) {
      int tosend = app.bufcnt << 1;
      while (nosefart_ip.output->buffer_free() < tosend && going) {
        xmms_usleep(30000);
      }
      nosefart_ip.add_vis_pcm(nosefart_ip.output->written_time(),
			      FMT_S16_LE, 1, tosend, app.bufptr);
      nosefart_ip.output->write_audio(app.bufptr, tosend);
      tosend >>= 1;
      app.bufcnt -= tosend; 
      app.bufptr += tosend; 
    }
  }
  pdebug("nsf : decoder loop end\n");
  SetChangeTrack(0, -1);
  ApplyChangeTrack();

  if (app.nsf) {
    nsf_free(&app.nsf);
    app.nsf = nsf = 0;
  }

  /* Make sure the output plugin stops prebuffering */
  if (nosefart_ip.output) {
    pdebug("nsf : free audio buffer.\n");
    nosefart_ip.output->buffer_free();
  }
  going = FALSE;
  pdebug("nsf : decode finish\n");
  play_thread = 0;
  pthread_exit(NULL);
}
Ejemplo n.º 4
0
static void
play_loop (GstPad * pad)
{
  GstFlowReturn ret;
  GstNsfDec *nsfdec;
  GstBuffer *out;
  gint64 value, offset, time;
  GstFormat format;

  nsfdec = GST_NSFDEC (gst_pad_get_parent (pad));

  out = gst_buffer_new_and_alloc (nsfdec->blocksize);
  gst_buffer_set_caps (out, GST_PAD_CAPS (pad));

  nsf_frame (nsfdec->nsf);
  apu_process (GST_BUFFER_DATA (out), nsfdec->blocksize / nsfdec->bps);

  /* get offset in samples */
  format = GST_FORMAT_DEFAULT;
  gst_nsfdec_src_convert (nsfdec->srcpad,
      GST_FORMAT_BYTES, nsfdec->total_bytes, &format, &offset);
  GST_BUFFER_OFFSET (out) = offset;

  /* get current timestamp */
  format = GST_FORMAT_TIME;
  gst_nsfdec_src_convert (nsfdec->srcpad,
      GST_FORMAT_BYTES, nsfdec->total_bytes, &format, &time);
  GST_BUFFER_TIMESTAMP (out) = time;

  /* update position and get new timestamp to calculate duration */
  nsfdec->total_bytes += nsfdec->blocksize;

  /* get offset in samples */
  format = GST_FORMAT_DEFAULT;
  gst_nsfdec_src_convert (nsfdec->srcpad,
      GST_FORMAT_BYTES, nsfdec->total_bytes, &format, &value);
  GST_BUFFER_OFFSET_END (out) = value;

  format = GST_FORMAT_TIME;
  gst_nsfdec_src_convert (nsfdec->srcpad,
      GST_FORMAT_BYTES, nsfdec->total_bytes, &format, &value);
  GST_BUFFER_DURATION (out) = value - time;

  if ((ret = gst_pad_push (nsfdec->srcpad, out)) != GST_FLOW_OK)
    goto pause;

done:
  gst_object_unref (nsfdec);

  return;

  /* ERRORS */
pause:
  {
    const gchar *reason = gst_flow_get_name (ret);

    GST_DEBUG_OBJECT (nsfdec, "pausing task, reason %s", reason);
    gst_pad_pause_task (pad);

    if (ret == GST_FLOW_UNEXPECTED) {
      /* perform EOS logic, FIXME, segment seek? */
      gst_pad_push_event (pad, gst_event_new_eos ());
    } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED) {
      /* for fatal errors we post an error message */
      GST_ELEMENT_ERROR (nsfdec, STREAM, FAILED,
          (NULL), ("streaming task paused, reason %s", reason));
      gst_pad_push_event (pad, gst_event_new_eos ());
    }
    goto done;
  }
}
Ejemplo n.º 5
0
 void __declspec(dllexport) DLL_FrameAdvance(void* nsf)
 {
   nsf_frame((nsf_t*)nsf);
 }