Esempio n. 1
0
void start_sound()
{
    while(read_sound_int(&SOUNDSTATUS->mode) != MODE_PLAY) {
        memset4((void*)RING_BUF, 0, SAMPLES_TO_BYTES(RING_BUFFER_SAMPLES+1));
        memset4((void*)RING_BUF+STEREO_OFFSET, 0, SAMPLES_TO_BYTES(RING_BUFFER_SAMPLES+1));

        do_sound_command(CMD_SET_MODE(MODE_PLAY));
    }
}
Esempio n. 2
0
void SSRunMixer(void)
{
	int bytes_copied;
	int bytestogo;
	int c;
	int i;
	int pos = read_sound_int(&SOUNDSTATUS->samplepos);

	memset(tmp_sound_buffer, 0, sizeof(tmp_sound_buffer));

	const int len = 2*SAMPLES_TO_BYTES(AUDIO_SIZE);

	// get data for all channels and add it to the mix
	for(c=0;c<SS_NUM_CHANNELS;c++)
	{
		if (channel[c].head==channel[c].tail) continue;
		
		bytestogo = len;
		mix_pos = 0;
		while(bytestogo > 0)
		{
			bytes_copied = AddBuffer(&channel[c], bytestogo);
			bytestogo -= bytes_copied;
			
			if (channel[c].head==channel[c].tail)
			{		// ran out of chunks before buffer full
				// clear remaining portion of mixbuffer
				if (bytestogo)
				{
					memset(&mixbuffer[mix_pos], 0, bytestogo);
				}
				
				break;
			}
		}
		
		MixAudio(tmp_sound_buffer, mixbuffer, len, channel[c].volume);

	}

	// tell any callbacks that had a chunk finish, that their chunk finished
	for(c=0;c<SS_NUM_CHANNELS;c++)
	{
		if (channel[c].FinishedCB)
		{
			for(i=0;i<channel[c].nFinishedChunks;i++)
			{
				//stat("Telling channel %d's handler that chunk %d finished", c, channel[c].FinishedChunkUserdata[i]);
				(*channel[c].FinishedCB)(c, channel[c].FinishedChunkUserdata[i]);
			}
		}
		
		channel[c].nFinishedChunks = 0;
	}

	memcpy4s(RING_BUF + pos, tmp_sound_buffer, SAMPLES_TO_BYTES(AUDIO_SIZE));
}
Esempio n. 3
0
static int siren14seek(struct ast_filestream *fs, off_t sample_offset, int whence)
{
	off_t offset = 0, min = 0, cur, max;

	sample_offset = SAMPLES_TO_BYTES(sample_offset);

	cur = ftello(fs->f);

	fseeko(fs->f, 0, SEEK_END);

	max = ftello(fs->f);

	if (whence == SEEK_SET)
		offset = sample_offset;
	else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
		offset = sample_offset + cur;
	else if (whence == SEEK_END)
		offset = max - sample_offset;

	if (whence != SEEK_FORCECUR)
		offset = (offset > max) ? max : offset;

	/* always protect against seeking past begining. */
	offset = (offset < min) ? min : offset;

	return fseeko(fs->f, offset, SEEK_SET);
}
Esempio n. 4
0
/* Called to copy samples to the decode fifo when we are doing
 * a transition - crossfade or fade in. This method applies gain
 * to both the new signal and the one that's already in the fifo.
 */
static void decode_transition_copy_bytes(sample_t *buffer, size_t nbytes) {
	sample_t sample, *sptr;
	int nsamples, s;
	size_t bytes_read;
	fft_fixed in_gain, out_gain;

	ASSERT_AUDIO_LOCKED();

	while (nbytes) {
		bytes_read = SAMPLES_TO_BYTES(transition_sample_step - transition_samples_in_step);

		if (bytes_read > nbytes) {
			bytes_read = nbytes;
		}

		nsamples = BYTES_TO_SAMPLES(bytes_read);

		sptr = (sample_t *)(void *)(decode_fifo_buf + decode_audio->fifo.wptr);

		in_gain = transition_gain;
		out_gain = FIXED_ONE - in_gain;

		if (crossfade_started) {
			for (s=0; s<nsamples * 2; s++) {
				sample = fixed_mul(out_gain, *sptr);
				sample += fixed_mul(in_gain, *buffer++);
				*sptr++ = sample;
			}
		}
		else {
			for (s=0; s<nsamples * 2; s++) {
				*sptr++ = fixed_mul(in_gain, *buffer++);
			}
		}

		fifo_wptr_incby(&decode_audio->fifo, bytes_read);
		nbytes -= bytes_read;

		transition_samples_in_step += nsamples;
		while (transition_samples_in_step >= transition_sample_step) {
			transition_samples_in_step -= transition_sample_step;
			transition_gain += transition_gain_step;
		}
	}
}
Esempio n. 5
0
void *memcpy4s(void *s1, const void *s2, unsigned int n)
{
    unsigned int *p1a = s1;
    unsigned int *p1b = (void*)(((char *)s1)+SAMPLES_TO_BYTES(STEREO_OFFSET));
    const unsigned int *p2 = s2;
    n+=3;
    n>>=2;
    while(n--) {
#if SAMPLE_MODE == 0
        unsigned int a = *p2++;
        unsigned int b = *p2++;
        *p1a++ = (a & 0xffff) | ((b & 0xffff)<<16);
        *p1b++ = ((a & 0xffff0000)>>16) | (b & 0xffff0000);
#else
#error 8 bit stereo not implemented...
#endif
    }
    return s1;
}
Esempio n. 6
0
static bool_t upload_samples(sample_t *buffer, u32_t nsamples) {
	ssize_t n, len;

	if (!upload_fd) {
		return FALSE;
	}

	len = SAMPLES_TO_BYTES(nsamples);
	while (len) {
		n = send(upload_fd, buffer, len, 0);
		if (n < 0) {
			LOG_WARN(log_audio_decode, "send failed (%s)", strerror(errno));
			upload_close();
			break;
		}

		len -= n;
	}

	return TRUE;
}
Esempio n. 7
0
static int g719seek(struct ast_filestream *fs, off_t sample_offset, int whence)
{
	off_t offset = 0, min = 0, cur, max;

	sample_offset = SAMPLES_TO_BYTES(sample_offset);

	if ((cur = ftello(fs->f)) < 0) {
		ast_log(AST_LOG_WARNING, "Unable to determine current position in g719 filestream %p: %s\n", fs, strerror(errno));
		return -1;
	}

	if (fseeko(fs->f, 0, SEEK_END) < 0) {
		ast_log(AST_LOG_WARNING, "Unable to seek to end of g719 filestream %p: %s\n", fs, strerror(errno));
		return -1;
	}

	if ((max = ftello(fs->f)) < 0) {
		ast_log(AST_LOG_WARNING, "Unable to determine max position in g719 filestream %p: %s\n", fs, strerror(errno));
		return -1;
	}

	if (whence == SEEK_SET)
		offset = sample_offset;
	else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
		offset = sample_offset + cur;
	else if (whence == SEEK_END)
		offset = max - sample_offset;

	if (whence != SEEK_FORCECUR)
		offset = (offset > max) ? max : offset;

	/* always protect against seeking past begining. */
	offset = (offset < min) ? min : offset;

	return fseeko(fs->f, offset, SEEK_SET);
}
Esempio n. 8
0
void decode_output_samples(sample_t *buffer, u32_t nsamples, int sample_rate) {
	size_t bytes_out;

	/* Some decoders can pass no samples at the start of the track. Stop
	 * early, otherwise we may send the track start event at the wrong
	 * time.
	 */
	if (nsamples == 0) {
		return;
	}

	// XXXX full port from ip3k

	decode_audio_lock();

	if (decode_first_buffer) {
		LOG_DEBUG(log_audio_decode, "first buffer sample_rate=%d", sample_rate);

		upload_open();

		crossfade_started = FALSE;
		decode_audio->track_start_point = decode_audio->fifo.wptr;
		
		if (decode_transition_type & TRANSITION_CROSSFADE) {
			size_t crossfadeBytes;
			fft_fixed interval;

			if (decode_transition_type & TRANSITION_IMMEDIATE) {
				size_t wanted = SAMPLES_TO_BYTES(decode_transition_period * decode_audio->track_sample_rate);
				size_t used = fifo_bytes_used(&decode_audio->fifo);

				if (used > wanted) {
					size_t skip = used - wanted;
					if (skip > decode_audio->fifo.wptr) decode_audio->fifo.wptr += decode_audio->fifo.size;
					decode_audio->fifo.wptr -= skip;
				}
			}

			/* We are being asked to do a crossfade. Find out
			 * if it is possible.
			 */
			interval = determine_transition_interval(sample_rate, decode_transition_period, &crossfadeBytes);

			if (interval) {
				LOG_DEBUG(log_audio_decode, "Starting CROSSFADE over %d seconds, requiring %d bytes", fixed_to_s32(interval), (unsigned int)crossfadeBytes);

				/* Buffer position to stop crossfade */
				crossfade_ptr = decode_audio->fifo.wptr;

				/* Buffer position to start crossfade */
				if (crossfadeBytes > decode_audio->fifo.wptr) decode_audio->fifo.wptr += decode_audio->fifo.size;
				decode_audio->fifo.wptr -= crossfadeBytes;

				/* Gain steps */
				transition_gain_step = fixed_div(FIXED_ONE, fixed_mul(interval, s32_to_fixed(TRANSITION_STEPS_PER_SECOND)));
				transition_gain = 0;
				transition_sample_step = sample_rate / TRANSITION_STEPS_PER_SECOND;
				transition_samples_in_step = 0;

				crossfade_started = TRUE;
				decode_audio->track_start_point = decode_audio->fifo.wptr;
			}
			/* 
			 * else there aren't enough leftover samples from the
			 * previous track, so abort the transition.
			 */
		}
		else if (decode_transition_type & TRANSITION_FADE_IN) {
			/* The transition is a fade in. */

			LOG_DEBUG(log_audio_decode, "Starting FADE_IN over %d seconds", decode_transition_period);

			/* Gain steps */
			transition_gain_step = fixed_div(FIXED_ONE, s32_to_fixed(decode_transition_period * TRANSITION_STEPS_PER_SECOND));
			transition_gain = 0;
			transition_sample_step = sample_rate / TRANSITION_STEPS_PER_SECOND;
			transition_samples_in_step = 0;
		}

		decode_audio->track_copyright = streambuf_is_copyright();
		decode_audio->track_sample_rate = sample_rate;

		decode_audio->check_start_point = TRUE;
		decode_first_buffer = FALSE;
	}

	if (upload_samples(buffer, nsamples)) {
		decode_audio_unlock();
		return;
	}
	
	/* If output_channels is set, copy left samples to right, or vice versa */
	if (output_channels) {
		unsigned int i;
		if (output_channels & OUTPUT_CHANNEL_LEFT) {
			for (i = 0; i < nsamples * 2; i += 2) {
				buffer[i+1] = buffer[i];
			}
		}
		else {
			for (i = 0; i < nsamples * 2; i += 2) {
				buffer[i] = buffer[i+1];
			}
		}
	}

	decode_apply_track_gain(buffer, nsamples);

	bytes_out = SAMPLES_TO_BYTES(nsamples);

	while (bytes_out) {
		size_t wrap, bytes_write, bytes_remaining;

		/* The size of the output write is limied by the
		 * space untill our fifo wraps.
		 */
		wrap = fifo_bytes_until_wptr_wrap(&decode_audio->fifo);

		/* When crossfading limit the output write to the
		 * end of the transition.
		 */
		if (crossfade_started) {
			bytes_remaining = decode_transition_bytes_remaining(crossfade_ptr);
			if (bytes_remaining < wrap) {
				wrap = bytes_remaining;
			}
		}

		bytes_write = bytes_out;
		if (bytes_write > wrap) {
			bytes_write = wrap;
		}

		if (transition_gain_step) {
			decode_transition_copy_bytes(buffer, bytes_write);

			if ((crossfade_started && decode_audio->fifo.wptr == crossfade_ptr)
			    || transition_gain >= FIXED_ONE) {
				LOG_DEBUG(log_audio_decode, "Completed transition");

				transition_gain_step = 0;
				crossfade_started = FALSE;
			}
		}
		else {
			memcpy(decode_fifo_buf + decode_audio->fifo.wptr, buffer, bytes_write);
			fifo_wptr_incby(&decode_audio->fifo, bytes_write);
		}

		buffer += (bytes_write / sizeof(sample_t));
		bytes_out -= bytes_write;
	}

	decode_audio_unlock();
}