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; }
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; }
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; }
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; }
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; }
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; }