PLAY WAV File VS1003B

Designing hardware that use VLSI Solution's devices as the system controller for the entire design.
Post Reply
adria_toa
User
Posts: 3
Joined: Wed 2021-04-14 8:33

PLAY WAV File VS1003B

Post by adria_toa »

Hi Panu,

Currently I have project using VS1003B.
How about to send WAV file? I try to send MP3 and it's OK but when try send WAV file there is no sound on output.

Here my init code

Code: Select all


uint8_t VSInitSoftware()
{
	WriteSci(SCI_MODE, SM_SDINEW | SM_OUTOFWAV | SM_RESET ); //|SM_SDISHARE|SM_TESTS|SM_RESET);
	WriteSci(SCI_CLOCKF,
			HZ_TO_SC_FREQ(12288000) | SC_MULT_03_30X | SC_ADD_03_10X);

	/*Set volume level at 0 db (0.5 db Steps) -> ((leftchannelx256)+rightchannel */
	WriteSci(SCI_VOL, 0x0000);	//Full Volume
	//WriteSci(SCI_BASS, 0x0055);
	WriteSci(SCI_DECODE_TIME, 0); //Reset Decode Time

	return 0;
}
Here's my play file function

Code: Select all

void playFile()
{
	uint32_t bytesInBuffer;
	uint32_t pos = 0;
	long nextReportPos=0;
	FRESULT		result;

	result = f_read(&AudioFile, playBuf, FILE_BUFFER_SIZE, (void*)&bytesInBuffer);
	if( result == FR_OK)
	{
		uint8_t *bufP = playBuf;

		while(bytesInBuffer){
			int t = min(SDI_MAX_TRANSFER_SIZE, bytesInBuffer);

			SendSDI(bufP, t);

			bufP += t;
			bytesInBuffer -= t;
			pos += t;
			/*If playback is going on as normal, see if we need to collect and update display lcd*/
			if(pos >= nextReportPos)
			{				
				h1 = ReceiveSci(SCI_HDAT1); //global variable
				nextReportPos += 4096;
				sampleRate = ReceiveSci(SCI_AUDATA); //global variable
				time = ReceiveSci(SCI_DECODE_TIME); //global variable
			}
		}
	}else
	{
		Player_Close();
	}
}
And here's SPI part code send data

Code: Select all

uint8_t SendSDI(uint8_t* buffer, uint8_t size)
{
	Mp3SelectData();	//xDCS = 0

	while(!CheckVS1003B_DRQ()); //Check DREQ pin
	if(HAL_SPI_Transmit(&VSSpiHandle, (uint8_t*)buffer, size, 500) != HAL_OK)
	{
		return 1;
	}

	Mp3DeselectData();	//xDCS = 1
	Mp3DeselectControl(); //xCS = 1

	return 0;
}
Is there special case if we want to send WAV or WMA file ?
Hannu
Senior User
Posts: 176
Joined: Mon 2016-05-30 11:54

Re: PLAY WAV File VS1003B

Post by Hannu »

adria_toa wrote: Wed 2021-04-21 4:06 Currently I have project using VS1003B.
How about to send WAV file? I try to send MP3 and it's OK but when try send WAV file there is no sound on output.


Here my init code
Which I modded and removed the stop playing wav bit.

Code: Select all


uint8_t VSInitSoftware()
{
	/*WriteSci(SCI_MODE, SM_SDINEW | SM_OUTOFWAV | SM_RESET ); //|SM_SDISHARE|SM_TESTS|SM_RESET);*/
	WriteSci(SCI_MODE, SM_SDINEW  | SM_RESET ); //|SM_SDISHARE|SM_TESTS|SM_RESET);
	WriteSci(SCI_CLOCKF,
			HZ_TO_SC_FREQ(12288000) | SC_MULT_03_30X | SC_ADD_03_10X);

	/*Set volume level at 0 db (0.5 db Steps) -> ((leftchannelx256)+rightchannel */
	WriteSci(SCI_VOL, 0x0000);	//Full Volume
	//WriteSci(SCI_BASS, 0x0055);
	WriteSci(SCI_DECODE_TIME, 0); //Reset Decode Time

	return 0;
}

Here's my play file function
Which will read one FILE_BUFFER_SIZE of bytes and transmit it. It may not be what you intended. I presume, you opened the AudioFile previously and then called playFile function.
And does your system really give some real object and not just a pointer to a something which could be called as file?

Usually I read files something like this:

Code: Select all

int bytes;
while (1) {
	bytes = fread(buf, 1, BUF_SIZE, fp);
	if (bytes <= 0)break;
	pos += bytes;
	SendSdi(buf, bytes);
	PrintInfoToScreen(pos);
}
With that kind of structure, the infoprint is contrerolled by BUF_SIZE and if you have for example 256 byte buffer, wrap the three first lines inside for-loop and iterate 16 times to get 4096. 4096 would come really fast with wav files. 8 kHz stereo 16-bit would be about 2*2*2 = 8 times in second
And here's SPI part code send data
Which I modded to respect DREQ and the 32 bytes. That way I think, the player function can be simplified.

What is the parameter 500 in HAL_SPI_Trasmit function?

Code: Select all

#define SAFELY_CAN_SEND_BYTES 32
uint8_t SendSDI(uint8_t* buffer, uint8_t size)
{
	int16_t toSend = bytes; /* Signed 16-bit handles case where size > 128 and can go to negative side. */
	Mp3DeselectControl(); //xCS = 1 Is this really needed? Does some function leave XCS down?
	while(toSend > 0) {
		while(!CheckVS1003B_DRQ()); //Check DREQ pin
		Mp3SelectData();	//xDCS = 0
		if(HAL_SPI_Transmit(&VSSpiHandle, (uint8_t*)buffer, SAFELY_CAN_SEND_BYTES , 500) != HAL_OK)
		{
			return 1;
		}
		Mp3DeselectData();	//xDCS = 1
		toSend -= SAFELY_CAN_SEND_BYTES ;
	}
	return 0;
}
Is there special case if we want to send WAV or WMA file ?
Not really. As long as clocks are high enough (PLL on VS1003 and SPI) I believe that you just set the SM_OUT_OF_WAV to jump out before you even stared to decode. Rest of this post I tried to make your code look nicer. :)
User avatar
pasi
VLSI Staff
Posts: 1795
Joined: Thu 2010-07-15 16:04

Re: PLAY WAV File VS1003B

Post by pasi »

Hannu is correct, you should not be setting SM_OUTOFWAV (SM_CANCEL) during the init.

When any audio decoder sees SM_CANCEL, it stops decoding, clears SM_CANCEL and returns to the main loop. For mp3 it's not critical, because only one frame of decoded audio gets lost, and the next mp3 frame starts the mp3 decoder again. But for other formats that have one header, the decoding will end even before it is started. Your controller will then send the rest of the file and the vs10xx is trying to find anything decodable from that data.

You can see the currently running decoder from HDAT1. If the value is 0, there is no decoding happening.

You should only use SM_CANCEL to cancel decoding when you switch songs (and at the end of tracks) -- but for vs1003b software reset probably works better.
Visit https://www.facebook.com/VLSISolution VLSI Solution on Facebook
adria_toa
User
Posts: 3
Joined: Wed 2021-04-14 8:33

Re: PLAY WAV File VS1003B

Post by adria_toa »

Which I modded and removed the stop playing wav bit.

Code: Select all


uint8_t VSInitSoftware()
{
	/*WriteSci(SCI_MODE, SM_SDINEW | SM_OUTOFWAV | SM_RESET ); //|SM_SDISHARE|SM_TESTS|SM_RESET);*/
	WriteSci(SCI_MODE, SM_SDINEW  | SM_RESET ); //|SM_SDISHARE|SM_TESTS|SM_RESET);
	WriteSci(SCI_CLOCKF,
			HZ_TO_SC_FREQ(12288000) | SC_MULT_03_30X | SC_ADD_03_10X);

	/*Set volume level at 0 db (0.5 db Steps) -> ((leftchannelx256)+rightchannel */
	WriteSci(SCI_VOL, 0x0000);	//Full Volume
	//WriteSci(SCI_BASS, 0x0055);
	WriteSci(SCI_DECODE_TIME, 0); //Reset Decode Time

	return 0;
}
Originally I did not use SM_OUTOFWAV. I set SM_OUTOFWAV because after play WAV file then next file is MP3, MP3 file won't play correctly.
Is it correct ?
Which will read one FILE_BUFFER_SIZE of bytes and transmit it. It may not be what you intended. I presume, you opened the AudioFile previously and then called playFile function.
And does your system really give some real object and not just a pointer to a something which could be called as file?

Usually I read files something like this:

Code: Select all

int bytes;
while (1) {
	bytes = fread(buf, 1, BUF_SIZE, fp);
	if (bytes <= 0)break;
	pos += bytes;
	SendSdi(buf, bytes);
	PrintInfoToScreen(pos);
}
With that kind of structure, the infoprint is contrerolled by BUF_SIZE and if you have for example 256 byte buffer, wrap the three first lines inside for-loop and iterate 16 times to get 4096. 4096 would come really fast with wav files. 8 kHz stereo 16-bit would be about 2*2*2 = 8 times in second
Yes i call fopen() function before playfile() function. Thank you for your reference code
Yes my system give real object of file from SDCARD and USB
Which I modded to respect DREQ and the 32 bytes. That way I think, the player function can be simplified.

What is the parameter 500 in HAL_SPI_Trasmit function?

Code: Select all

#define SAFELY_CAN_SEND_BYTES 32
uint8_t SendSDI(uint8_t* buffer, uint8_t size)
{
	int16_t toSend = bytes; /* Signed 16-bit handles case where size > 128 and can go to negative side. */
	Mp3DeselectControl(); //xCS = 1 Is this really needed? Does some function leave XCS down? //[b]Yes you right it's no needed[/b]
	while(toSend > 0) {
		while(!CheckVS1003B_DRQ()); //Check DREQ pin
		Mp3SelectData();	//xDCS = 0
		if(HAL_SPI_Transmit(&VSSpiHandle, (uint8_t*)buffer, SAFELY_CAN_SEND_BYTES , 500) != HAL_OK)
		{
			return 1;
		}
		Mp3DeselectData();	//xDCS = 1
		toSend -= SAFELY_CAN_SEND_BYTES ;
	}
	return 0;
}
500 is timeout parameter (ms) because it's blocking mode. When use DMA mode it doesn't work.
Not really. As long as clocks are high enough (PLL on VS1003 and SPI) I believe that you just set the SM_OUT_OF_WAV to jump out before you even stared to decode. Rest of this post I tried to make your code look nicer. :)
Noted thank you very much
pasi wrote: Wed 2021-04-21 11:06 Hannu is correct, you should not be setting SM_OUTOFWAV (SM_CANCEL) during the init.

When any audio decoder sees SM_CANCEL, it stops decoding, clears SM_CANCEL and returns to the main loop. For mp3 it's not critical, because only one frame of decoded audio gets lost, and the next mp3 frame starts the mp3 decoder again. But for other formats that have one header, the decoding will end even before it is started. Your controller will then send the rest of the file and the vs10xx is trying to find anything decodable from that data.

You can see the currently running decoder from HDAT1. If the value is 0, there is no decoding happening.

You should only use SM_CANCEL to cancel decoding when you switch songs (and at the end of tracks) -- but for vs1003b software reset probably works better.
Noted thank you very much

And one last thing do you have tips/trick how to fast forward or fast backward the mp3/wav/wma file ?
User avatar
pasi
VLSI Staff
Posts: 1795
Joined: Thu 2010-07-15 16:04

Re: PLAY WAV File VS1003B

Post by pasi »

adria_toa wrote: Thu 2021-04-22 6:32Originally I did not use SM_OUTOFWAV. I set SM_OUTOFWAV because after play WAV file then next file is MP3, MP3 file won't play correctly.
Is it correct ?
If you give a software reset between the tracks, it restarts the decoder. The decoder is always looking for something to decode when you start sending the file.
adria_toa wrote: Thu 2021-04-22 6:32And one last thing do you have tips/trick how to fast forward or fast backward the mp3/wav/wma file ?
For mp3 it's very simple -- send some zero-bytes (to make sure the current mp3 frame gets filled), then start sending from the new position. The decoder will look for the next mp3 frame header and resynchronize automatically.

For WAV and WMA in vs1003b rewind / goto is not simple...

For WMA see VS1003b WMA Webcast / Rewind Patch from http://www.vlsi.fi/en/support/software/ ... tches.html .

For WAV you would probably need to modify the "data" chunk size to 0 or 0xffffffff in the wav header you send, then you need to skip a multiple of the (stereo) samples in the data (probably a multiple of 4 bytes, because vs1003 only supports 8-bit and 16-bit mono and stereo formats). Without adjusting the data size the playback would end prematurely when you skip backwards.

Later vs10xx chips also have a "fast play" option.
Visit https://www.facebook.com/VLSISolution VLSI Solution on Facebook
Post Reply