How to speed up some operations (for pitch funcionality)

Status
Not open for further replies.

Sandro

Well-known member
Hi all,
I devoped a scrath of code which introduces a pitch functionality in play_serialflash_raw, using linear interpolation for calculating missing samples. This is my fork on Github:
https://github.com/PaulStoffregen/Audio/pull/259

this code runs fine, but apparently not fast enough to allow poliphony. This is the "core" part of the code that I'd like to boost:

Code:
void AudioPlaySerialflashRaw::update(void)
{
	unsigned int i, n;
	audio_block_t *block;
	int16_t samples_vector[2000]; 		// ***** current vector of samples read from file	
	int32_t h, k, j; 			// ***** indexes of samples
	float virtual_index; 			// ***** likely not integer index
	float index_delta; 			// ***** mantissa of virtual_index
	int16_t h_sample_value, k_sample_value; // ***** samples value
	int f, g, w; 				// ***** variables
	int16_t samples_to_read; 		// ***** number of samples

	// only update if we're playing
	if (!playing) return;

	// allocate the audio blocks to transmit
	block = allocate();
	if (block == NULL) return;

	if (rawfile.available()) {

		// ***** my main code starts here
		t_0=micros(); // ***** calculating the computational time
		first_index_to_read=((ride==0)? 0 :last_index_to_read+1);
		last_index_to_read=ceil(((ride*128)+127)*pitch);
		samples_to_read=last_index_to_read-first_index_to_read+1;

		// ***** this part of code reads from file up to 128 samples per time; if we read more than 128 samples there are errors!. The result is the samples_vector[samples_to_read]			
		f=samples_to_read%128;
		g=samples_to_read/128;
		
		// ***** read one group of "f" samples
		n = rawfile.read(block->data, f*2); 
		file_offset += n;
		for (i=n/2; i < f; i++) {
			block->data[i] = 0;
		}
		for (i=0; i < f; i++) {
			samples_vector[i]=block->data[i];
		}
		
		// ***** read "g" groups of 128 samples
		for (w=0; w<g; w++)	{ 
	  		n = rawfile.read(block->data, 128*2); // ***** read one group of f samples
			file_offset += n;
			for (i=n/2; i < 128; i++) {
				block->data[i] = 0;
			}
			for (i=0; i < 128; i++) {
				samples_vector[f+(w*128)+i]=block->data[i];
			}
		}
		// ***** samples_vector[samples_to_read] is ready!	
		
		// ***** calculating block->data[128]
		for (i=0;i<128;i++) {
			j=i+(128*ride);
			virtual_index=(float)(j)*pitch;         // ***** virtual (it means that can be not-integer) index of the needed sample
			h=floor(virtual_index); 		// ***** index of the lower sample needed for calculation
			k=ceil(virtual_index);  		// ***** index of the upper sample needed for calculation
			index_delta=virtual_index-h;  	        // ***** mantissa
			h=h-first_index_to_read; 		// ***** lower (relative) index of the sample needed for calculation 
			k=k-first_index_to_read;	 	// ***** upper (relative) index of the sample needed for calculation
			h_sample_value =((h==-2)? penultimate_sample: ((h==-1)? last_sample: samples_vector[h])); 	// ***** value of the lower sample needed for calculation
			k_sample_value =((k==-2)? penultimate_sample: ((k==-1)? last_sample: samples_vector[k])); 	// ***** value of the upper sample needed for calculation
			block->data[i]=h_sample_value + (index_delta*(k_sample_value-h_sample_value)); 				// ***** value of the calculated sample
		}		
		penultimate_sample=samples_vector[k-1]; 	// ***** value of the penultimate sample read from file will be used in the next ride
		last_sample=samples_vector[k]; 				// ***** value of the last sample read from file will be used in the next ride
		ride ++;
		t=micros()-t_0; // ***** calculating the computational time "t"
		// ***** my main code ends here
				
		transmit(block);
	}

Any suggestion? To be honest I did'nt check the poliphony of the original/unmodified play_serialflash_raw.cpp.
Thank you!
 
Status
Not open for further replies.
Back
Top