示例#1
0
文件: naplay.c 项目: EQ4/rsynth
void
audio_play(int n,short *data)
{
 int endian = 1;
#define little_endian ((*((char *)&endian) == 1))
 int priv = 0;
 AuEvent ev;
 Sound s = SoundCreate(SoundFileFormatNone, little_endian ?
                       AuFormatLinearSigned16LSB : AuFormatLinearSigned16MSB,
                       1, samp_rate, n, "Chit chat");
 if (aud)
  {
#ifdef USE_ALL_ARGS
   AuStatus ret_status;
   AuFlowID flow = 0;
   int monitor = 0;
   int multiplier = 0;
   if (!AuSoundPlayFromData(aud, s, data, AuNone,
                            AuFixedPointFromFraction(volume, 100),
                            done, &priv,
                            &flow, &multiplier,
                            &monitor, &ret_status))
#else
   if (!AuSoundPlayFromData(aud, s, data, AuNone,
                            AuFixedPointFromFraction(volume, 100),
                            done, &priv,
                            NULL, NULL, NULL, NULL))
#endif
    perror("problems playing data");
   else
    {
     while (1)
      {
       AuNextEvent(aud, AuTrue, &ev);
       AuDispatchEvent(aud, &ev);
       if (priv)
        break;
      }
    }
  }
 SoundDestroy(s);
}
示例#2
0
static int
sound_nas_play(audio_job_t aj)
{
	/* stream stuff */
	Lisp_Media_Stream *ms;
	media_substream *mss;
	/* thread stuff */
	media_thread_play_state mtp;
	/* device stuff */
	Lisp_Object device;
	Lisp_Audio_Device *lad = NULL;
	sound_nas_data_t *snd = NULL;
	/* nas stuff */
	AuElement elms[3];
	AuStatus as;
	int bsize = 0;
	/* subthread stuff */
	sound_nas_aj_data_t _snsd, *snsd = &_snsd;
	sxe_mse_volume_args _volargs, *volargs = &_volargs;
	sxe_mse_rerate_args _rrargs, *rrargs = &_rrargs;
	/* cache stuff */
	int alloced_myself = 0;

	SOUND_UNPACK_MT(aj, device, ms, mss, lad, snd, snsd->mtap);

	/* refuse to do anything if the AuServer pointer is not set */
	if (snd->aud == NULL) {
		NAS_DEBUG_C("b0rked connection, gute Nacht!\n");
		return 0;
	}

	/* install error handlers before anything else */
	AuSetErrorHandler(snd->aud, nas_error_handler);
	AuSetIOErrorHandler(snd->aud, nas_IOerror_handler);

	/* find physical output device */
	snsd->dev = nas_find_device(snd->aud, snsd->mtap->channels);

	if (snsd->dev == AuNone ||
	    !(snsd->flow = AuCreateFlow(snd->aud, NULL))) {
		/* No physical output device found or flow creation failed. */
		NAS_DEBUG_C("no physical devices for this stream\n");
		return 0;
	}

	/* A system call interrupted with a SIGALRM or SIGIO
	   comes back here */
	if (SETJMP(nas_server_sig)) {
		NAS_CRITICAL("Caught the lethal signal.\n");
		snd->aud = NULL;
		sound_nas_finish(snd);
		goto uhoh;
	}

	/* init the snsd */
	snsd->samplerate = 0;
	snsd->framesize = (snsd->channels = snsd->mtap->channels)
		* sizeof(int16_t);
	snsd->msf = MEDIA_SAMPLE_FORMAT(sxe_msf_S16);
	snsd->coe_ch_cnt = 0;
	snsd->resolution =
		(snsd->mtap->samplerate * MTPSTATE_REACT_TIME) / 1000000;
	bsize = (snsd->resolution + NAS_FRAG_SIZE - 1) & ~(NAS_FRAG_SIZE-1);

	snsd->snd = snd;
	snsd->buffer_size = bsize;
	snsd->writepos = snsd->readpos = 0;
	snsd->overfill = snsd->underrun = 0;

	/* set up flow */
	AuMakeElementImportClient(elms+0, snsd->mtap->samplerate,
				  AuFormatLinearSigned16LSB,
				  snsd->mtap->channels,
				  AuTrue,
				  bsize, bsize / 2,
				  0, NULL);
	snsd->gain = AuFixedPointFromFraction(1, 1);
	AuMakeElementMultiplyConstant(elms+1, 0, snsd->gain);
	AuMakeElementExportDevice(elms+2, 0, snsd->dev,
				  snsd->mtap->samplerate,
				  AuUnlimitedSamples, 0, NULL);
	AuSetElements(snd->aud, snsd->flow, AuTrue, 3, elms, &as);

	if (as != AuSuccess) {
		NAS_DEBUG_C("play(): AuSetElements failed\n");
		return 0;
	}

#if 0				/* atm we insist on having stereo access */
	/* the channel effect */
	ADD_MEDIA_SAMPLE_EFFECT(
		snsd->coe_chain, snsd->coe_ch_cnt,
		MEDIA_SAMPLE_EFFECT(sxe_mse_2ch_to_1ch), NULL);
#endif

	/* the volume effect */
	ADD_MEDIA_SAMPLE_EFFECT(
		snsd->coe_chain, snsd->coe_ch_cnt,
		MEDIA_SAMPLE_EFFECT(sxe_mse_volume), volargs);
	volargs->num_channels = snsd->channels;
	snsd->volargs = volargs;

	/* the rerate effect */
	ADD_MEDIA_SAMPLE_EFFECT(
		snsd->coe_chain, snsd->coe_ch_cnt,
		MEDIA_SAMPLE_EFFECT(sxe_mse_rerate), rrargs);
	rrargs->num_channels = snsd->channels;
	rrargs->srcrate = rrargs->tgtrate = 1;
	snsd->rrargs = rrargs;

	AuRegisterEventHandler(snd->aud, AuEventHandlerIDMask |
			       AuEventHandlerTypeMask,
			       AuEventTypeElementNotify, snsd->flow,
			       nas_event_handler, (AuPointer)aj);

	/* rewind the stream */
	media_stream_meth(ms, rewind)(mss);

	/* play chunks of the stream */
	SXE_MUTEX_LOCK(&aj->mtx);
	if (aj->buffer_alloc_size < SOUND_MAX_AUDIO_FRAME_SIZE) {
		alloced_myself = 1;
		aj->buffer = xmalloc_atomic(SOUND_MAX_AUDIO_FRAME_SIZE);
		aj->buffer_alloc_size = SOUND_MAX_AUDIO_FRAME_SIZE;
	}
	SXE_MUTEX_UNLOCK(&aj->mtx);
	snsd->mtp = MTPSTATE_STOP;
	snsd->volume = -1;
	audio_job_device_data(aj) = snsd;

	/* prefill the buffer */
	NAS_DEBUG_S("prefill the buffer: %d\n", 4*bsize);
	if (!nas_fill(aj, 4*bsize))
		goto uhoh;

	while (aj->play_state != MTPSTATE_STOP) {

#if 0
		if (aj->volume != snsd->volume) {
			AuElementParameters aep;
			NAS_DEBUG_S("Setting volume.\n");
			snsd->volume = aj->volume;
			snsd->gain = AU_FIXED_POINT_SCALE*(snsd->volume)/127;
			aep.parameters[AuParmsMultiplyConstantConstant] =
				snsd->gain;
			aep.flow = snd->flow;
			aep.element_num = 1;
			aep.num_parameters = AuParmsMultiplyConstant;

			AuSetElementParameters(snd->aud, 1, &aep, &as);
			if (as != AuSuccess) {
				NAS_DEBUG_S("Setting volume failed.\n");
			}
		}
#endif

#ifdef EF_USE_ASYNEQ
		/* events for me audio-job? */
		if (audio_job_queue(aj)) {
			sound_nas_handle_aj_events(aj);
		}
#endif

		SXE_MUTEX_LOCK(&aj->mtx);
		mtp = aj->play_state;
		SXE_MUTEX_UNLOCK(&aj->mtx);
		switch (mtp) {
		case MTPSTATE_RUN:
			if (snsd->mtp != mtp) {
				NAS_DEBUG("ah, gotta work again\n");
				AuStartFlow(snd->aud, snsd->flow, &as);
				if (as != AuSuccess) {
					NAS_DEBUG_C("play(): "
						    "AuStartFlow failed\n");
					aj->play_state = MTPSTATE_STOP;
				}
			}
			nas_empty_event_queue(snsd);
			usleep(snsd->resolution);
			break;
		case MTPSTATE_PAUSE:
			if (snsd->mtp != mtp) {
				NAS_DEBUG("sleeping for %d\n",
					  snsd->resolution);
				AuStopFlow(snd->aud, snsd->flow, &as);
			}
			usleep(snsd->resolution);
			break;

		case MTPSTATE_UNKNOWN:
		case MTPSTATE_STOP:
		case NUMBER_OF_MEDIA_THREAD_PLAY_STATES:
		default:
			NAS_DEBUG("ACK, quit\n");
			AuStopFlow(snd->aud, snsd->flow, &as);
			SXE_MUTEX_LOCK(&aj->mtx);
			aj->play_state = MTPSTATE_STOP;
			SXE_MUTEX_UNLOCK(&aj->mtx);
			break;
		}
		snsd->mtp = mtp;
	}

uhoh:
	/* -- Close and shutdown -- */
	SXE_MUTEX_LOCK(&aj->mtx);
	if (alloced_myself && aj->buffer) {
		xfree(aj->buffer);
	}
	aj->buffer = NULL;
	aj->buffer_alloc_size = 0;
	SXE_MUTEX_UNLOCK(&aj->mtx);

	return 1;
}