playsdwav, play from the specific time of the file.

Status
Not open for further replies.

byungjun

Member
Hello,
I wander if there's a possibility to play audio file from the certain time of the file, not from the beginning?
The second question is accurate syncing of several files while playing.

Best, Jun
 
Hello,

There is no quick function to do that, but it's pretty simple to add. Depending on your project.
Also, implementation actually depend of if you are playing WAV or RAW audio files. I suggest to start with RAW files for ease.
You will have to add a couple of things in the "play_sd_raw.cpp" library file.
Here is a simplified example for a modified play() public method. My explainations in the comments :
Code:
// dont forget to define it BEFORE play()
// this work better with teensy 3.5 - 3.6.
#define B2M (uint32_t)((double)4294967296000.0 / AUDIO_SAMPLE_RATE / 2.0) // 97352592
// On older teensys use :
//#define B2M (uint32_t)((double)4294967296000.0 / AUDIO_SAMPLE_RATE_EXACT / 2.0) // 97352592


bool AudioPlaySdRaw::play(const char *filename, int32_t startPosMs ) // We pass the parameter "startPosMs" that will be used. dont forget to update the .h file too
{
	stop();
#if defined(HAS_KINETIS_SDHC)
	if (!(SIM_SCGC3 & SIM_SCGC3_SDHC)) AudioStartUsingSPI();
#else
	AudioStartUsingSPI();
#endif
	__disable_irq();
	rawfile = SD.open(filename);
	__enable_irq();
	if (!rawfile) {
		//Serial.println("unable to open file");
		#if defined(HAS_KINETIS_SDHC)
			if (!(SIM_SCGC3 & SIM_SCGC3_SDHC)) AudioStopUsingSPI();
		#else
			AudioStopUsingSPI();
		#endif
		return false;
	}
	
	// Get the file size in bytes

	file_size = rawfile.size();

	// init the file offset to zero at start, we will modify it later

	file_offset = 0;
	
	// Here we convert the total raw byte size to Milliseconds, assuming your sample rate is 44100khz
	// Now you get the total duration in MS

	uint64_t duration = ((uint64_t)file_size * B2M) >> 32;

	// Because of the byte nature of things, we need to seek the file in discrete increments. If not (arbitrary value) you will hear terrible distortion.
	// Here, the slice padding is 2 blocks, we calculate the number of blocks in the entire file.

	uint32_t dataSlicedBlocksNb = dataSize / AUDIO_BLOCK_SAMPLES * 2; // ---------------> You can also write : datasize >> 8;
	
	// Be carrefull of the limits! Here I just add 20ms padding on maximum, to prevent unpredicable results.

	if (startPosMs < duration - 20) {

		// Now map the range to adapt MS values to a block safe environement

  		file_offset = startPosMs * dataSlicedBlocksNb / duration; 

  		// Then run block by 2 blocks
  		
  		file_offset *= AUDIO_BLOCK_SAMPLES * 2; 

		// finally, seek the data

  		rawfile.seek(file_offset);

	} 

	playing = true;
	return true;
}

Now, for .Wav files. You'II have a lot of coding/dealing with non audio data. But the principle is the same. A good example of how it can be implemented is the TomWhitwell/RadioMusic module. Take a look : https://github.com/TomWhitwell/RadioMusic/blob/master/RadioMusic/SDPlayPCM.cpp

Hope it help!
Cheers.
 
Thank you so much for your reply and it is good starting point for me.
I'll try it and see if it works.
Again I do appreciate your help.

Best, Jun
 
Status
Not open for further replies.
Back
Top