| View previous topic :: View next topic |
| Author |
Message |
PrimeTime
Joined: 19 Aug 2004 Posts: 25
|
Posted: Sun Aug 22, 2004 5:46 pm Post subject: Streaming large PCM from the HDD |
|
|
Hi again,
I'm trying to stream a large PCM audio file from my hard drive.
I'm using the SjPCM library to help. My problem is, the sound output
is very choppy. I am not sure if it is coming from reading the data
from the hard drive, or transferring the data to the right and left
audio channels. Here is the code of my stream algor.
| Code: |
samples1 = malloc(800);
scr_printf("Loading.. ");
//Just some pre-loading
fileXioRead(fd, (short*)samples1, 800);
for (readIn = 0; readIn < 800; readIn++)
{
left[readIn] = samples1[readIn];
if (channels == 2) right[readIn] = samples1[2*readIn+1]; else right[readIn] = samples1[readIn];
}
while (1)
{
buffered = SjPCM_Buffered();
if (buffered<1*800)
{
SjPCM_Enqueue(left, right, 800, 0); // avoid underrun
fileXioRead(fd, (short*)samples1, 800);
for (i=0; i<800; i++)
{
left[i] = samples2[i];
if (channels == 2) right[i] = samples2[2*i+1]; else right[i] = samples2[i];
}
wait_vsync();
}
}
|
my audio file is the correct format for SjPCM. I've tried different buffer sizes too, ranging from 800 to 768000.
The larger buffersizes pause during rebuffering.
Any ideas?
Thanks,
Ryan |
|
| Back to top |
|
 |
Guest
|
Posted: Sun Aug 22, 2004 7:01 pm Post subject: |
|
|
One problem I have looking at your code is that you did not include
any of your variable declarations, such as for:
samples1, samples2, left[], right[], etc...
Its hard to debug other peoples code if you can't make sure their problem
isn't in their variable declarations.
Not that it necessarily is so, I heard a similar problem discussed in
#ps2dev[efnet] recently. Maybe someone else can drop by to offer
some hints, or you could try dropping into the channel and asking.
Gorim |
|
| Back to top |
|
 |
PrimeTime
Joined: 19 Aug 2004 Posts: 25
|
Posted: Sun Aug 22, 2004 7:12 pm Post subject: |
|
|
sorry about that, made a few typos
| Code: |
samples1 = malloc(800);
scr_printf("Loading.. ");
//Just some pre-loading
fileXioRead(fd, (short*)samples1, 800);
for (readIn = 0; readIn < 800; readIn++)
{
left[readIn] = samples1[readIn];
if (channels == 2) right[readIn] = samples1[2*readIn+1]; else right[readIn] = samples1[readIn];
}
while (1)
{
buffered = SjPCM_Buffered();
if (buffered<1*800)
{
SjPCM_Enqueue(left, right, 800, 0); // avoid underrun
fileXioRead(fd, (short*)samples1, 800);
for (i=0; i<800; i++)
{
left[i] = samples1[i];
if (channels == 2) right[i] = samples1[2*i+1]; else right[i] = samples1[i];
}
wait_vsync();
}
}
|
samples1 is short*
left and right are static short __attribute__((aligned (64)))[1024] |
|
| Back to top |
|
 |
Saotome

Joined: 03 Apr 2004 Posts: 182
|
Posted: Sun Aug 22, 2004 7:22 pm Post subject: |
|
|
i'm not sure if thats the cause for your choppy output, but shouldn't it be:
| Code: |
for (i=0; i<800; i++)
{
if (channels == 2) left[i] = samples1[2*i]; //<= !!!
else left[i] = samples1[i];
if (channels == 2) right[i] = samples1[2*i+1]; else right[i] = samples1[i];
}
|
? _________________ infj |
|
| Back to top |
|
 |
PrimeTime
Joined: 19 Aug 2004 Posts: 25
|
Posted: Sun Aug 22, 2004 7:47 pm Post subject: |
|
|
thats incorrect code for 2 channels :D
I'm trying a mono channel right now, so i can just use the left data for both, I have re-written the algorithm, it works a little better, but once the initial buffer is empty it gets choppy.
I can't find anything wrong, but its also late at night.
| Code: |
short *samples1 = malloc(192000);
fileXioRead(fd, (short*)samples1, 192000);
readIn = 0;
i = 0;
while (1)
{
left[iSamples] = samples1[readIn];
if ( (++iSamples == 800)) //800 samples are now in left[]
{
wait_vsync();
SjPCM_Enqueue(left, left, 800, 0); // queue up the 800 samples
//read 800 more samples in the buffer location i just transferred to left[]
fileXioRead(fd, (short*)&samples1[i*800], 800);
i++; //increment the buffer block
iSamples = 0; //reset the queued samples
}
if (++readIn == 192000) // we are at the end of the buffer
{
printf("------Getting new data--------\n");
readIn = 0;
i = 0; //since we reread the buffer while we were playing, we should be able to reset the variables and transfer the new buffer
}
}
|
|
|
| Back to top |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Mon Aug 23, 2004 11:39 am Post subject: |
|
|
Reading 800 samples at a time off the HD won't work. There's no cacheing in the HD code, so it needs to get the data off the drive in non-optimal sizes (not multiples of the blocksize). The HD is incapable of randomly getting 800 samples within one video frame. Some will, and others won't leading to chop. You need to buffer at least a couple seconds ahead.
Create a thread that keeps a two-second buffer full of data which is read (at least) 8K at a time. Have another thread that waits a video frame, then feeds data to the sound. |
|
| Back to top |
|
 |
PrimeTime
Joined: 19 Aug 2004 Posts: 25
|
Posted: Mon Aug 23, 2004 3:53 pm Post subject: |
|
|
Ah, I figured it out.
I haven't used threads for the streaming yet, but I did get
the file to stream correctly.
My problem was that each sample is 2 bytes which is
stored in one element of a short array
I was treating the short array as it it were an
array of 1 byte elements such as a char array.
So, my output was choppy since i was transferring
only the first portion of the stream and not the second.
Ryan |
|
| Back to top |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Tue Aug 24, 2004 9:48 am Post subject: |
|
|
| Wow! I'm surprised. That you can pull the data off the HDD one frame at a time says quite a bit for how good the drive code is. I'd have thought for certain you'd need a threaded buffer to keep it smooth. Good to hear otherwise, but I think it'd be much better with a threaded buffer. |
|
| Back to top |
|
 |
mrbrown
Joined: 17 Jan 2004 Posts: 1536
|
Posted: Wed Aug 25, 2004 4:12 am Post subject: |
|
|
| J.F. wrote: | | Wow! I'm surprised. That you can pull the data off the HDD one frame at a time says quite a bit for how good the drive code is. I'd have thought for certain you'd need a threaded buffer to keep it smooth. Good to hear otherwise, but I think it'd be much better with a threaded buffer. |
Er, it's a hard drive, with <5ms seek time and 20-25MB/s peek transfer speed (at least under PS2/Linux, it's probably more natively).
Why wouldn't it be fast enough? _________________ "He was warned..." |
|
| Back to top |
|
 |
J.F.
Joined: 22 Feb 2004 Posts: 2906
|
Posted: Wed Aug 25, 2004 9:21 am Post subject: |
|
|
| I'd read somewhere else on the forum that the current HD code was SLOW (getting less than 1M/s transfer rates). I guess what we need is a nice test that shows how fast certain types and size of transfers are, and what their latency is. |
|
| Back to top |
|
 |
PrimeTime
Joined: 19 Aug 2004 Posts: 25
|
Posted: Wed Aug 25, 2004 11:02 am Post subject: |
|
|
Well, either way, I got both the threaded and non-threaded versions
to work :)
Ryan |
|
| Back to top |
|
 |
mrbrown
Joined: 17 Jan 2004 Posts: 1536
|
Posted: Wed Aug 25, 2004 11:15 am Post subject: |
|
|
| J.F. wrote: | | I'd read somewhere else on the forum that the current HD code was SLOW (getting less than 1M/s transfer rates). I guess what we need is a nice test that shows how fast certain types and size of transfers are, and what their latency is. |
Well, HDD does compete with SMAP for the same interrupt and DMA channel. If we're still using the older, GPL'd SMAP driver (are we?) then we aren't contending for DMA because that driver doesn't use any. I remember reading the post from the guy that optimized SMAP and ps2ip and he had real abysmal rates transferring to the HDD over the network, IIRC.
I guess it would be worthwhile if someone sat down and benchmarked it. _________________ "He was warned..." |
|
| Back to top |
|
 |
|