예제 #1
0
파일: pwm.c 프로젝트: OpenEmu/picodrive
static void consume_fifo_do(SH2 *sh2, unsigned int m68k_cycles,
  int sh2_cycles_diff)
{
  struct Pico32xMem *mem = Pico32xMem;
  unsigned short *fifo_l = mem->pwm_fifo[0];
  unsigned short *fifo_r = mem->pwm_fifo[1];
  int sum = 0;

  if (pwm_cycles == 0 || pwm_doing_fifo)
    return;

  elprintf(EL_PWM, "pwm: %u: consume %d/%d, %d,%d ptr %d",
    m68k_cycles, sh2_cycles_diff, sh2_cycles_diff / pwm_cycles,
    Pico32x.pwm_p[0], Pico32x.pwm_p[1], pwm_ptr);

  // this is for recursion from dreq1 writes
  pwm_doing_fifo = 1;

  for (; sh2_cycles_diff >= pwm_cycles; sh2_cycles_diff -= pwm_cycles)
  {
    if (Pico32x.pwm_p[0] > 0) {
      fifo_l[0] = fifo_l[1];
      fifo_l[1] = fifo_l[2];
      fifo_l[2] = fifo_l[3];
      Pico32x.pwm_p[0]--;
      mem->pwm_current[0] = convert_sample(fifo_l[0]);
      sum += mem->pwm_current[0];
    }
    if (Pico32x.pwm_p[1] > 0) {
      fifo_r[0] = fifo_r[1];
      fifo_r[1] = fifo_r[2];
      fifo_r[2] = fifo_r[3];
      Pico32x.pwm_p[1]--;
      mem->pwm_current[1] = convert_sample(fifo_r[0]);
      sum += mem->pwm_current[1];
    }

    mem->pwm[pwm_ptr * 2    ] = mem->pwm_current[0];
    mem->pwm[pwm_ptr * 2 + 1] = mem->pwm_current[1];
    pwm_ptr = (pwm_ptr + 1) & (PWM_BUFF_LEN - 1);

    if (--Pico32x.pwm_irq_cnt == 0) {
      Pico32x.pwm_irq_cnt = pwm_irq_reload;
      do_pwm_irq(sh2, m68k_cycles);
    }
  }
  Pico32x.pwm_cycle_p = m68k_cycles * 3 - sh2_cycles_diff;
  pwm_doing_fifo = 0;
  if (sum != 0)
    pwm_silent = 0;
}
예제 #2
0
uint32 AudioBuffer::copyTo(
	AudioBuffer& target,
	uint32* pioFromFrame,
	uint32* pioTargetFrame,
	uint32 frames) const {

	// simplest case:	
	if(formatSameAs(target))
		return rawCopyTo(target, pioFromFrame, pioTargetFrame, frames);

	// sanity checks
	ASSERT(m_pData);
	ASSERT(m_frames);
	ASSERT(target.m_pData);

	// figure byte offsets & sizes
	uint32 fromOffset = *pioFromFrame * m_frameSize;
	uint32 targetOffset = *pioTargetFrame * m_frameSize;
	
	uint32 size = m_frames * m_frameSize;	
	uint32 targetSize = target.m_frames * target.m_frameSize;

	// figure number of samples to convert
	uint32 toCopy = frames * m_format.channel_count;	
	if(target.m_bCircular) {
		if(toCopy > targetSize)
			toCopy = targetSize;
	} else {
		if(toCopy > (targetSize-targetOffset))
			toCopy = (targetSize-targetOffset);
	}
	uint32 remaining = toCopy;
	
	uint32 sampleSize = m_frameSize / m_format.channel_count;

	// convert and copy a sample at a time
	for(; remaining; remaining -= sampleSize) {
		convert_sample(
			(void*) ((int8*)m_pData + fromOffset),
			(void*) ((int8*)target.m_pData + targetOffset),
			m_format.format,
			target.m_format.format);
		
		fromOffset += sampleSize;
		if(fromOffset == size)
			fromOffset = 0;
		
		targetOffset += sampleSize;
		if(targetOffset == targetSize)
			targetOffset = 0;
	}
	
	// write new offsets
	*pioFromFrame = fromOffset / m_frameSize;
	*pioTargetFrame = targetOffset / m_frameSize;
	
	return toCopy;
}
예제 #3
0
uint32 AudioBuffer::findMax(uint32 fromFrame, uint32 frameCount,
	float* pMax, uint32* pAt /*=0*/) const {

	size_t channels = m_format.channel_count;
	size_t samples = m_frames * channels;
	size_t bytesPerSample = m_format.format & 0x0f;

	size_t firstSample = fromFrame * channels;
	size_t remaining = frameCount * channels;

	if(!m_pData)
		return fromFrame;
		
	int8* pCur = (int8*)m_pData + (firstSample * bytesPerSample);

	uint32 n;

	if(pAt) {
		// reset pAt
		for(n = 0; n < channels; n++)
			pAt[n] = UINT32_MAX;
	}
	
	// find minimum for each channel
	for(
		n = firstSample;
		remaining;
		remaining--, n++, pCur += bytesPerSample) {
		
		// wrap around to start of buffer?
		if(n == samples) {
			pCur = (int8*)m_pData;
			n = 0;
		}
				
		float fCur = 0;
		convert_sample(pCur, fCur, m_format.format);
		
		if(fCur > pMax[n % channels]) {
			pMax[n % channels] = fCur;
			if(pAt)
				pAt[n % channels] = n / channels;
		}
	}
	
	// return current frame
	return n / channels;
}
예제 #4
0
uint32 AudioBuffer::findPeaks(uint32 fromFrame, uint32 frameCount,
	float* pPeaks, uint32* pAt) const {
	
	size_t channels = m_format.channel_count;
	size_t samples = m_frames * channels;
	size_t bytesPerSample = m_format.format & 0x0f;

	size_t firstSample = fromFrame * channels;
	size_t remaining = frameCount * channels;

	if(!m_pData)
		return fromFrame;
	int8* pCur = (int8*)m_pData + (firstSample * bytesPerSample);

	uint32 n;

	if(pAt) {
		// reset pAt
		for(n = 0; n < channels; n++)
			pAt[n] = ULONG_MAX;
	}

	// find peaks in both directions
	for(
		n = firstSample;
		remaining;
		remaining--, n++, pCur += bytesPerSample) {
		
		// wrap around to start of buffer?
		if(n == samples) {
			pCur = (int8*)m_pData;
			n = 0;
		}
				
		float fCur = 0;
		convert_sample(pCur, fCur, m_format.format);
		
		if(fabs(fCur) > pPeaks[n % channels]) {
			pPeaks[n % channels] = fCur;
			if(pAt)
				pAt[n % channels] = n / channels;
		}
	}
	
	// return current frame
	return n / channels;
}
예제 #5
0
uint32 AudioBuffer::average(uint32 fromFrame, uint32 frameCount,
	float* pAverage) const {
	
	size_t channels = m_format.channel_count;
	size_t samples = m_frames * channels;
	size_t bytesPerSample = m_format.format & 0x0f;

	size_t firstSample = fromFrame * channels;
	size_t remaining = frameCount * channels;

	if(!m_pData)
		return fromFrame;
	int8* pCur = (int8*)m_pData + (firstSample * bytesPerSample);

	// clear averages
	memset(pAverage, 0, sizeof(float)*channels);
	
	// calculate
	uint32 n;
	for(
		n = firstSample;
		remaining;
		remaining--, n++, pCur += bytesPerSample) {
			
		// wrap around to start of buffer
		if(n == samples) {
			pCur = (int8*)m_pData;
			n = 0;
		}
				
		float fCur = 0;
		convert_sample(pCur, fCur, m_format.format);

		pAverage[n%channels] += fCur;
	}

	for(uint32 n = 0; n < channels; n++)
		pAverage[n] /= frameCount;	
	
	// return current frame
	return n / channels;
}
예제 #6
0
NuvieIOBuffer *ConverseSpeech::load_speech(std::string filename, uint16 sample_num)
{
 unsigned char *compressed_data, *raw_audio, *wav_data;
 sint16 *converted_audio;
 uint32 decomp_size;
 uint32 upsampled_size;
 sint16 sample=0, prev_sample;
 U6Lib_n sam_file;
 U6Lzw lzw;
 NuvieIOBuffer *wav_buffer = 0;
 uint32 j, k;
 
 sam_file.open(filename, 4);
 
 compressed_data = sam_file.get_item(sample_num, NULL);
 raw_audio = lzw.decompress_buffer(compressed_data, sam_file.get_item_size(sample_num), decomp_size);
 
 free(compressed_data);
 
 if(raw_audio != NULL)
  {
   wav_buffer = new NuvieIOBuffer();
   upsampled_size = decomp_size + (int)floor((decomp_size - 1) / 4) * (2 + 2 + 2 + 1);

   switch((decomp_size - 1) % 4)
    {
     case 1 : upsampled_size += 2; break;
     case 2 : upsampled_size += 4; break;
     case 3 : upsampled_size += 6; break;
    }
   
   DEBUG(0,LEVEL_DEBUGGING,"decomp_size %d, upsampled_size %d\n", decomp_size, upsampled_size);
   
   wav_data = (unsigned char *)malloc(upsampled_size * sizeof(sint16) + 44); // 44 = size of wav header
   
   wav_buffer->open(wav_data, upsampled_size * sizeof(sint16) + 44, false);
   wav_init_header(wav_buffer, upsampled_size);
   
   converted_audio = (sint16 *)&wav_data[44];
   
   prev_sample = convert_sample(raw_audio[0]); 
   
   for(j=1,k=0;j<decomp_size;j++,k++)
    {
     converted_audio[k] = prev_sample;

     sample = convert_sample(raw_audio[j]);

     switch(j % 4) // calculate the in-between samples using linear interpolation.
       {
        case 0 : 
        case 1 : 
        case 2 : 
                 converted_audio[k+1] = (sint16)(0.666 * (float)prev_sample + 0.333 * (float)sample);
                 converted_audio[k+2] = (sint16)(0.333 * (float)prev_sample + 0.666 * (float)sample);             
                 k += 2;
                 break;
        case 3 : converted_audio[k+1] = (sint16)(0.5 * (float)(prev_sample + sample));
                 k += 1;
                 break;
       }

     prev_sample = sample;
    }
    
   converted_audio[k] = sample;
  }
 
 free(raw_audio);
  
 return wav_buffer;
}