How to do USB audio
Pages: 1 ... 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 ... 52
Dave Higton (1515) 3526 posts |
Look at the definition of what you put in the string pointed to by R0. If your device is USB10, then the string should be “USB10”. Check the value of playhandle after you’ve tried to open it. It should be non-zero. Anyway, it looks as if you’ve made it work. I don’t understand what your code to transfer bytes does. Have you tried using the current version of UAPlayer with a WAV file with 32 bits per sample? That ought to work, if your device is going to at all.
Your best bet for code is to enclose it in pre and /pre tags within angle brackets. Try in the “Test” forum. |
jim lesurf (2082) 1438 posts |
I think I’d tried that and got silence. The program didn’t crash, though. So I’ll give it another try. The if(playhandle==0)is meant to catch if I got a null back from the call. The block transfers at the top let me count/transfer offsets in bytes (pretending to be chars) or 4-byte ints. One of the things I’ll check when my mind is clearer tomorrow if if I got the offsets correct! The device I’m using is the DAC Magic Plus which, using your/Colin’s programs, plays OK. I did finally find pre, but only after trying TT and code. Both of which ‘half work’ in ways that made it look as if I was just using them incorrectly. Thanks! This had made my head muzzy with struggling. I’ll give it another go tomorrow. Jim |
jim lesurf (2082) 1438 posts |
Sorry my previous post isn’t clear and accurate. Apologies, my brain is really fogged at present by banging my head against the screen so much! IIRC The DMPlus works OK with Colin’s player/module. But if I use Dave’s player it doesn’t. AIUI this is because all my wav files are 16bit or 24bit but the DAC needs to be fed 4 bytes per value. However for my hard-wired test I have generated a bufferfull of 4-byte integer values (stereo pairs so 8 bytes per pair) to give to the DAC. I’d assume that the USBAudio module would then be happy because I’m trying to send 4byte values to a DAC that wants 4bytes per value. Is that wrong? Is that the problem? Can’t the USBAudio DAC support and understand that? For now I’ve just been synthesising the values earlier in the program (test sinewave on one channel). The idea being once this works I can sort out reading a real wave file, and also using the results of the USBAudio calls to set up the transfer rather than simply dictating as I do now the values given to USBAudio_OpenOut. Jim |
Ronald May (387) 407 posts |
“I don’t think you need to double buffer” |
Colin (478) 2433 posts |
You want something like this Jim
For your devices with a 32bit subFrameSize you need to shift any data so that the most significant bit of your data is bit 31. So if you have 16 bit data the data is bits 31:16 and 15:0 will be 0 |
Dave Higton (1515) 3526 posts |
Let me confirm – is this with the version that is currently on my web site? I thought I had overcome the problem. You need to have a WAV file whose samples are of the correct subframe size because the app does not attempt to pad data out. However, if your DAC offers the correct subframe size but a lower resolution than the file professes to contain, the USBAudio module takes that as a match rather than rejecting it. But I’ve only been able to check it with a 24-bit file to a 20-bit device. I did this by taking a track ripped from a CD, and using Audacity to save it as 24 bits per sample. You can do the same to save it as 32 bits per sample, which would be right for your DAC. |
Dave Higton (1515) 3526 posts |
There may be a basic misunderstanding. The USBAudio module only gets information from devices, controls them, and opens streams to/from them. It takes no part in the real time transfer of audio data. DeviceFS buffers are inherently circular, but you don’t need to think about it. For audio output, you have to read the space available in the buffer, and keep the buffer from emptying. I recommend putting in whole numbers of samples for all channels; if the buffer empties completely, it should do so on a sample boundary. Complementary considerations apply for audio input – in this case you’re trying to prevent the buffer from filling completely. |
Colin (478) 2433 posts |
I’ve just got an interesting web cam. Microphone is rubbish but the camera sends uncompressed YUY2 video -whatever that is – so looks a good candidate to get something working. |
Ronald May (387) 407 posts |
Dave,
So this rounds the amount of buffer I want to use down to the nearest multiple of 12 (so I can always work with a multiple of six 2 byte samples.) |
jim lesurf (2082) 1438 posts |
So far as I can see, that’s much the same as I’m using apart from being written ‘GCC style’ rather than in the more ‘Acorn’ style I’ve used for years, and allowing for minor changes like my dac is normally USB10, etc, in the values. I’m also using a block of 8000 samples because that follows what seems to work with, say, Colin’s player. Have you checked that what you listed works on a 4-byte per value transfer to a DAC like the DMPlus? I’m using fwrite as that is more compatable with standard ‘C’ rather than using something like a GBPB call. That’s the only obvious difference which may be the key. So I’ll try GBPB although I think they should be equivalent. (?) Jim |
jim lesurf (2082) 1438 posts |
At present I am not playing a ‘wave file’. I generate in advance a block of values that should ‘match’ what my DAC says it wants fed to it. Because the dac wants 4-bytes per sample, I generate a set of (4-byte) signed ints in LRLRLR… order in the block. I then use fwrite to write that block a few times to the output stream/file. What you’ve said seems to confirm my understanding that this should work because the actual transfers simply send the values. If I’d got the byte ordering wrong I’d have expected rude noises from the DAC rather than my intended test tone. But I get no output. Just tried again this morning having correct another minor error (which didn’t change anything) and setting the name back to “USB10”. (The program checks this before trying to use it, so I know the DAC is USB10 when the program is run.) The first time I ran the program it crashed. But it told me it had started playing – which only happens if it doesn’t get caught by the handle == 0 trap. So the handle given wasn’t zero. If I then try again I get it halting because the handle returned is now zero. And if I try to use Colin’s player it tells me the endpoint is ‘in use’ which confirmed that I’d Opened it, but not closed it again. That was because on my first try I’d put the Close inside the part of the code that would only be run if the handle wasn’t zero. But even moving it so it would always run after an attempt to open also now failed. Presumably because it couldn’t know the handle value! :-) I’ll do some more experiments and see if I can find any significant differences between my version and Ron’s. At first glance they seem equivalent to me. BTW I did a swi listing to find the SWI numbers and have used #defines like Ron’s. Your API doesn’t seem to list the numbers. It would be nice if you did, but I presume these may be subject to change until they may be ‘officially adopted’? Jim |
Colin (478) 2433 posts |
The file handle returned by USBAudio_OpenOut is a RISC OS file handle not a C file handle you can’t use stdio functions like fwrite. |
jim lesurf (2082) 1438 posts |
Ah! Ok, I’ll try GBPB. Why are these different, though? Is there a ‘STREAM*’ type? I’d wondered about it being ‘FILE*’. Jim |
jim lesurf (2082) 1438 posts |
Ok, some progress. Having changed to using OS_GBPB I now get some audio out and the program doesn’t crash. But I think I’m overwhelming the bufferring. Having changed to use GBPB I got a very short ‘squark’ from the DAC. Didn’t last as long as it should. I also noticed that the LEDs on the front didn’t change to show the 96k rate I’d asked for. Stayed showing the default (48k). So I fudged the code to tell USBAudio_OpenOut the rate was 48k. On the basis that this could use the same test data but just play it at a lower sample rate. This then give a short burst of tone on one channel. i.e. the right kind of waveform output, but still only for a short time. So I modified the program to tell me something about the values returned in This now gives *ram:runimage Hello world! List of devices by ID = USB10 Found USB10 Device string 1 => Cambridge Audio Device string 2 => Cambridge Audio USB Audio 2.0 Done resolutions = 1 play using 24 bits per sample Rates buffer size used/needed = 28 play ch = 2 res = 24 bytes/ch = 4 lpcm number of rates = 5 Rate 1 = 44100 Rate 2 = 48000 Rate 3 = 88200 Rate 4 = 96000 Rate 5 = 192000 Test outblock created 96k rate start play 0 GBPB => 0 C0 1 GBPB => 28928 C1 C2 C3 C4 C5 C6 C7 C8 C9play done * Which seems to confirm that I’m sending fresh sets of data before the previous ones have been taken and played. So how do I control this? Or am I not understanding? (Note that the printout saying the created rate is 96k is now fibbing as I left that alone and just changed the rate I gave to USBAudio_OpenOut.) I’ll experiment with using a much smaller buffer in case that helps. Or is the problem that I should transfer much smaller blocks whilst having given the OpenOut a might bigger buffer size than the blocks I’m then transferring? FWIW The code now looks like: void playout(void) { char sblock[32]; int* iblock; FILE* playhandle; int playcount,playstop; iblock=(int*)sblock; iblock[0]=48000; /* sample rate */ sblock[4]=(char)24; sblock[5]=(char)4; sblock[6]=(char)2; sblock[7]=(char)1; sblock[8]=(char)0; iblock[3]=32000; rin.r[0]=(int)"USB10"; rin.r[1]=(int)sblock; _kernel_swi(USBAudio_OpenOut,&rin,&rout); playhandle=(FILE*)rout.r[0]; if(playhandle==0) { printf("Open failed!\n"); } else { printf("start play\n"); playcount=0; playstop=300; do { rin.r[0]=2; rin.r[1]=(int)playhandle; rin.r[2]=(int)outblock; rin.r[3]=32000; _kernel_swi(OS_GBPB,&rin,&rout); if (rout.r[3] != 32000) printf("%3d GBPB => %d\n",playcount,rout.r[3]); if(playcount<10) printf(" C%d",playcount); playcount++; } while (playcount<playstop); } rin.r[0]=(int)playhandle; _kernel_swi(USBAudio_Close,&rin,&rout); printf("play done\n"); } Jim |
Colin (478) 2433 posts |
FILE* is used to present a common filing system interface for all operating systems in C. The actual filing is done by the RISC OS filing system. Somewhere inside the FILE struct will be the RISC OS file handle but this is private to the stdio functions. There isn’t a |
Colin (478) 2433 posts |
do this
note the routs and the rins. |
jim lesurf (2082) 1438 posts |
Thanks Colin! :-) Now works OK at 48k. I had to change the order to do { _kernel_swi(OS_GBPB,&rin,&rout); rin.r[2] = rout.r[2]; rin.r[3] = rout.r[3]; } while (rout.r[3] != 0); to let the first calls work. It then works perfectly for 48k. :-)) The puzzle now is that I can’t seem to be able to change the sample rate and have this detected by the DAC. Whatever value I give for the If I give it 44100 I get the same tone as giving it 48000. i.e. No change in playout rate and hence the same pitch for the tone. If I give it 96000 the result is a very distorted tone. The LED on the DAC still shows 48k I think I’m using Dave’s most recent module version, but I’ll download the current one and check. From the code you gave I guess the method is to keep calling, updating where the transfers got to, until the whole input buffer has been transferred? Any comments wrt how big the buffer I’m using for data to send, and the buffer value given to USBAudio_OpenOut should be? I’m not clear on: Is using a ‘supply’ buffer in my program of 8000 ints (32000 bytes) far too big? Should I use a buffer size for GBPB which is somewhat smaller than my ‘supply’ buffer. i.e. each call of GBPB right from the first, only transfers to fill a part of the buffer size I’ve told the OpenOut to set/use/expect? I’m not clear on the meaning and effect of that value given to the OpenOut. Thanks again. :-) And sorry that I’ve never understood these things before, so am so easily baffled. Jim N.B Later addition: I just tried using Colin’s Player to play a 96k file. This changed the DAC LED/rate to 96k and played OK. I could then set the rate in my program to 96k and the results played OK. But 48k then would not, and gave distorted results. So it looks like my program simply fails to change the rate setting of the DAC. However if the rate at which I play matches what the DAC is already set to, it works. The problem isn’t that 96k is ‘too fast’, but some lack of agreement and setting the required rate if it isn’t already set. |
Colin (478) 2433 posts |
Yes it looks like the frequency isn’t being set – the device probably defaults to 48000. Dave will have to clarify that one I can’t see any other way of setting the samplerate in the USBAudio API. The usb buffer size ( |
jim lesurf (2082) 1438 posts |
I look at it the other way around. I like ‘C’ because it is as close as I can get to writing assembler. :-) More seriously, I can sometimes work out how some ARM assembler works. But I really struggle with how to write any to do something. No idea now how my ‘style’ (sic) for writing ‘C’ first came to me, but it is – of course – really FORTRAN trying to be assembler. 8-] So WRT buffer size it looks like bigger is safer than smaller. I’ll switch to using 0.2 or 0.25 secs. Once that is working I’ll see about reading in wave files and converting 16/24 data payloads to the required 4-byte format and see if I can then play something more interesting than a test tone. Before that, I’ll add a way of getting the process to stop if I hit a key or – if possible – click the mouse over the GraphTask window. I’ll stick with using your player to ‘change rate’ for now. Hopefully Dave can either point out my idiocy or fix any problem in the USBAudio module. Once that is sorted I’ll have the program take its play settings from the data supplied by asking the DAC what it requires rather than the current method where I simply hard-wire the details in the program because I know them for the specific DAC. I’m not sure if the rate problem is because I’m feeding the rate setting to USBAudio_OpenOut incorrectly, or if it is a bug in the module. Dave will have to say. However I’ve checked and I seem to be using the current version of the module. Maybe this is an issue due to the DAC being one I’ll call a (to keep Dave happy) ‘Release 2’ one. :-) The only alternative that’s occurred to me and I’ve not yet tested is that I set the rate and then start sending data too soon. So maybe not giving time for the DAC to react and change rate before data starts to arrive. Jim |
Dave Higton (1515) 3526 posts |
“Holding” reply: there is code to set the sample rate for both Release 1 and Release 2 devices, but the two releases control sample rates in entirely different ways, and I don’t have a Release 2 device to test it on. It’s a long time since I wrote the code, so I’m now in a better state to read and error check the code than just after I wrote it :-) If I can’t find my error, I’ll find a way to make diagnostics available. If I do, UAPlayer will be a good basis, so I really would appreciate your trying the current version to see if it works. To do that, clearly you would have to create a WAV file with 32 bit stereo samples, at the sample rate your DAC is currently set to. |
Dave Higton (1515) 3526 posts |
Right, I can see what’s wrong. I haven’t worked out how long it will take me to fix it yet, though. I will, as always, keep you posted! |
Dave Higton (1515) 3526 posts |
OK, there’s a new version of the module on my web site in USBAudio.zip. No doubt you’ll let me know if this fixes the problem. |
Dave Higton (1515) 3526 posts |
That was the plan – but I think it’s about time I fixed the numbers for what we have. |
Raik (463) 2061 posts |
I have try my EasyCAP device. Manufacturer: Syntek Semiconductor
DecodeDesc failed with Interface 1 alternate setting: 0 I have insert in the IsocRecorder IF usb$ = "" THEN If I try I become usb_control: bmRType=0×22 bRequest=0×1 wValue=0×100 wIndex=0×84 wLength=0×3 buf=0xA9E8 Recording to: ‘RAM:$.ISOOut/wav’ Press any key to stop recording The wav file is not working with the players… Change to interface 1 alternate 0 gives usb_control: bmRType=0×22 bRequest=0×1 wValue=0×100 wIndex=0×84 wLength=0×3 buf=0xA9E8 Cannot find a valid endpoint at line 126 I play around with the endpoints… no success. Sorry, I need help :-( Thanks. |
Colin (478) 2433 posts |
The original setting looks correct from the data you have supplied. Could you run USBDescriptors.zip it will give me a better picture of the device. |
Pages: 1 ... 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 ... 52