VS1053b ADTS Stream does not play

Writing software for systems that use VLSI Solution's devices as slave codecs to a host microcontroller.
StefanM
User
Posts: 8
Joined: Thu 2017-08-24 23:18

Re: VS1053b ADTS Stream does not play

Post by StefanM »

pasi wrote: Fri 2017-09-01 14:17 playChunk looks fine. I assume SPI.transfer() returns when the transfer has been finished (does it have a return value?), in which case the delays are not necessary.
Yes, it returns. Some Quote from the documentation: "SPI.transfer is based on a simultaneous send and receive: the received data is returned".

pasi wrote: Fri 2017-09-01 14:17 The one suspect thing is using two conditions in the byte send loop (i < 48 && buffer->space < 1024). 48 tells me you have a 48*32 = 1536-byte buffer, which is 3 disk blocks. What does buffer->space contain? Can the loop be exited early in some cases?
buffer is a queue (first-in-first-out) with the size of (32 Byte * 1024 =) 32 KByte. This queue is filled by data received from Wifi-/HTTP-Connection.
Internal my queue is a simple one-dimension-array.
buffer->read() returns a pointer to the current reading-position.
buffer->write() returns a pointer to the current writing-position.
To reduce the overhead of each function call the queue is seperated in (logical!) parts of 32 Bytes, so every read-call reads 32 Bytes.
My HTTP-receive-function writes directly 32 Bytes into the queue using buffer->write(), so I do not need to copy memory.

Code: Select all

uint8_t data_block[this->chunkSize * this->amount];	//32 * 1024

//public reading access
uint8_t *RingBuffer::read() {
	space++;						//Now more space is available. space is public accessable and was set at the beginning to 1024 by constructor
	return this->get(&this->index_read);
}
//public writing access
uint8_t *RingBuffer::write() {
	space--;						//Now less space is available
	return this->get(&this->index_write);
}

//private internal function
uint8_t *RingBuffer::get(uint16_t *index) {			//this->chunkSize is set to 32
	uint8_t *buf = &this->data_block[((*index) * this->chunkSize)];	//get a pointer to an array field
	(*index)++;										//increase the writing/reading index
	if(*index == this->amount) {				//jump back to the first index, when the buffer is full (ringbuffer)
		*index = 0;						//this->amount is set to 1024
	}
	return buf;
}
However, the loop (i < 48 && buffer->space < 1024) reads now 32 Byte in each iteration and sends them using playChunk(..).
The loop runs 48-times, but only as long as we have current data in queue - that is necessary to prevent reading old data from the queue.
So 1536 Bytes are send each time, normaly. The queue is filled regulary with new data, so normaly it works good.
User avatar
Panu
VSDSP Expert
Posts: 2829
Joined: Tue 2010-06-22 13:43

Re: VS1053b ADTS Stream does not play

Post by Panu »

Hi

If you'd like to zip and post your source code, I might be able to compile it to see what is happening.

-Panu
User avatar
pasi
VLSI Staff
Posts: 2122
Joined: Thu 2010-07-15 16:04

Re: VS1053b ADTS Stream does not play

Post by pasi »

Is there any container in the http-receive protocol that needs to be stripped?

If there is any chance for an out-of-order packet transmission, you are handling that?
Visit https://www.facebook.com/VLSISolution VLSI Solution on Facebook
StefanM
User
Posts: 8
Joined: Thu 2017-08-24 23:18

Re: VS1053b ADTS Stream does not play

Post by StefanM »

Panu wrote: Sun 2017-09-03 9:11 Hi

If you'd like to zip and post your source code, I might be able to compile it to see what is happening.

-Panu
Thank you for your very kind offer! I would like to accept :D
pasi wrote: Mon 2017-09-04 12:56 Is there any container in the http-receive protocol that needs to be stripped?
I strip the HTTP-Reponse-Headers (200 OK HTTP/1.1, Content-Length and so on including the last "\r\n\r\n") nothing more.
Wenn I download the file on my PC, I can play it well. So I do not think I need to strip more.
pasi wrote: Mon 2017-09-04 12:56 If there is any chance for an out-of-order packet transmission, you are handling that?
Hmm...., I dont handle it myself. I thought TCP would handle this for me, am I wrong?

~Stefan
Attachments
StefanM - Code VS1053b MP3 Noise M4A Dont Play.zip
(9.34 KiB) Downloaded 207 times
User avatar
Panu
VSDSP Expert
Posts: 2829
Joined: Tue 2010-06-22 13:43

Re: VS1053b ADTS Stream does not play

Post by Panu »

Thank you for the code. Seems I don't have just the necessary hardware at hand to test it so I've tried to review it in my head. Here's some first thoughts:

I think this is wrong:

Code: Select all

	for(; max >= 0 && rbuf->space > 0; max -= chunkSize) {	//Receive data larger or equal to blocksize
should be:

Code: Select all

	for(; max > 0 && rbuf->space > 0; max -= chunkSize) {	//Receive data larger or equal to blocksize
I think this is dangerous:

Code: Select all

void VS1053::playChunk(uint8_t* data, size_t len)
{
  digitalWrite(dcs_pin, LOW);
  delayMicroseconds(1); // tXCSS  
  await_data_request();
  while ( len )
  {
	await_data_request();
    SPI.transfer(*data++);
	len--;
  }
  
  delayMicroseconds(1); // tXCSH
  digitalWrite(dcs_pin,HIGH);
}
because whether delayMicroseconds(1) is enough depends on the SPI speed. It would be better to wait until the transmitter is idle, but for a quick test, just increase the amount of microseconds to see if it makes a difference or not.

Maybe try these to see if it makes any difference...
I strip the HTTP-Reponse-Headers (200 OK HTTP/1.1, Content-Length and so on including the last "\r\n\r\n") nothing more.
So there isn't any Icy-Metadata (Icy-MetaInt) in the header - it's just a raw binary file?

-Panu
StefanM
User
Posts: 8
Joined: Thu 2017-08-24 23:18

Re: VS1053b ADTS Stream does not play

Post by StefanM »

You've got it!
It works prefectly now; mp3 plays as well as m4a (192kb/s) does :D
You both are great! ;)
Panu wrote: Tue 2017-09-05 13:20 I think this is wrong:

Code: Select all

	for(; max >= 0 && rbuf->space > 0; max -= chunkSize) {	//Receive data larger or equal to blocksize
should be:

Code: Select all

	for(; max > 0 && rbuf->space > 0; max -= chunkSize) {	//Receive data larger or equal to blocksize
This was one of two mistakes!
The other was a wrong assumption:

Code: Select all

client->read(rbuf->write(), 32);
I thought client->read(..) would write always 32 Bytes, of course it does not :roll: . 32 Bytes specified the upper border, the maximum size of the buffer. But not the amount of Bytes I want to receive.
So client->read(..) returned sometimes less than 32 Bytes, this causes the buffer to contain zeros or if the buffer has already been filled to contain old data.

And sometimes it returns even nothing because "max = 0".

Panu wrote: Tue 2017-09-05 13:20 because whether delayMicroseconds(1) is enough depends on the SPI speed.
Anyway, I checked this out, but there is no difference even when I remove the delay.


So, I think this topic can be marked as "Solved" and can be closed. Thanks for your great help :mrgreen:

Best Regards
Stefan
Post Reply