The Speak text-to-speech module processes text into phonemes and then into a lower level form of formants (peaks in the frequency spectrum) which are then queued for output (the "wcmdq")
Speak registers a RISC_OS "Linear Sound Handler" (SWI &40145) which runs as an interrupt (IRQ mode? I'm not sure of the correct terminology) whenever the sound DMA needs filling. Speak's sound handler takes items from this wcmdq and converts them to the sound waveform to put into the sound DMA.
When the wcmdq gets low, the sound handler sets a transient callback (SWI &54) to ask the OS to run the user mode part of the module to convert some more text->phonemes->wcmdq.
This all works properly in the currently available Speak version 2, where the sound handler is written entirely in assembler.
I'm now trying to port a re-write which I did on Linux (espeak.sourceforge.net) to RISC_OS. I don't want to write the sound waveform generation code in assembler, so the only assembler code is a few lines of the sound handler which calls a C function and then sets the callback if needed.
But calling the C function from the sound handler gives: not enough memory - stack overflow filecore in use (which of course means the system then needs a restart).
The callback-setting is commented out, so that's not the problem.
Calling a dummy C function (one which just assigns a couple of variables) is OK. No error.
Calling a dummy C function which then calls another dummy C function gives the error and doesn't return.
I've checked the ARM procedure calling protocols and I think that's OK. The test code is:
IMPORT DummyProc1
DMA_Handler ;********** ; linear sound handler, fill the sound DMA ; preserve r11,r12,r13 (fp,ip,sp) ; r1,r2 start and end of DMA buffer
MOV r5,ip ; need to save ip MOV ip,sp ;set up a stack STMFD sp!, {fp,ip,lr,pc}
MOV r6,r1 ;DMA start 16 bit sound MOV r7,r2 ;DMA end
SUB r0,r7,r6 ;r0 = size of DMA buffer BL DummyProc1 ; which then calls DuumyProc2
When the error occurs, the NOP isn't reached (i.e. DummyProc1 doesn't return).
Am I doing something wrong, or is it just not possible to call a chain of C functions from assembler in general, or from a sound handler in particular?
-- change nospam in the reply email address to "jsd"
Jonathan Duddingon wrote: > The Speak text-to-speech module processes text into phonemes and then > into a lower level form of formants (peaks in the frequency spectrum) > which are then queued for output (the "wcmdq")
> Speak registers a RISC_OS "Linear Sound Handler" (SWI &40145) which
Why? Registering a linear sound handler is deprecated in favour of using SharedSound, which is a true multi-client system that avoids the race conditions caused by different tasks each attempting to control the sound system.
The PRM says the previous linear sound handler should be restored immediately that a task or module has finished play back. This means if the linear handler that your handler superceded naively deregisters then it will cause your linear handler to be displaced. Worse, when your client attempts to deregister it will restore a handler that no longer exists (resulting in a big crash). The only guard against this is for tasks or modules with handlers that have been superceded to refuse to quit (thus forcing the user to quit them in reverse order of registration).
In my opinion replacing the default linear handler (SharedSound) is just as anti-social as replacing the default channel handler (SoundChannels) was in the old days. But perhaps you have good reason.
> runs as an interrupt (IRQ mode? I'm not sure of the correct > terminology) whenever the sound DMA needs filling.
A comment in my own linear handler code (used as fallback when SS is not available) says 'IRQ or SVC mode, interrupts disabled'. Dunno where I got this info from.
The thing about interrupts is very important because if they were enabled then you would be unable to do anything that corrupts R14_IRQ (not even use the BL instruction!). This would definitely rule out compiled C code. However it appears that unlike an 8 bit voice generator, interrupts are not enabled upon entry.
> Speak's sound > handler takes items from this wcmdq and converts them to the sound > waveform to put into the sound DMA.
> When the wcmdq gets low, the sound handler sets a transient callback > (SWI &54) to ask the OS to run the user mode part of the module to > convert some more text->phonemes->wcmdq.
> This all works properly in the currently available Speak version 2, > where the sound handler is written entirely in assembler.
> I'm now trying to port a re-write which I did on Linux > (espeak.sourceforge.net) to RISC_OS. I don't want to write the sound > waveform generation code in assembler, so the only assembler code is a > few lines of the sound handler which calls a C function and then sets > the callback if needed.
> But calling the C function from the sound handler gives: > not enough memory - stack overflow > filecore in use > (which of course means the system then needs a restart).
Perhaps because you haven't set up the stack limit? (sl/r10) You probably ought to disable software stack limit checking on function entry, since nothing practical can be done to extend the privileged mode stacks.
Your C code mustn't attempt to access static data because the pointer to the base of static data for a given module instantiation is assumed to be stored 536 bytes below the stack limit. I imagine this would be difficult to replicate in your veneer.
You will instead have to define a C structure to hold the static data required by your buffer fill code (so that the format is known) and pass a pointer to this in R2 when registering your sound linear handler. This pointer will be passed to your handler code in a1/r0.
In article <4e10767094nos...@jsd.clara.co.uk>, Jonathan Duddingon <nos...@jsd.clara.co.uk> wrote:
> I've checked the ARM procedure calling protocols and I think that's OK. > The test code is:
> [snip]
> When the error occurs, the NOP isn't reached (i.e. DummyProc1 doesn't > return).
> Am I doing something wrong, or is it just not possible to call a chain > of C functions from assembler in general, or from a sound handler in > particular?
Sadly, assembler veneers to C functions are a little more complicated than that. The C library stores a couple of words (called the relocation modifiers) at the bottom of the SVC stack which help it to locate the current program's variables, etc.
In your C program somewhere during initialisation, you need to take a copy of those two words and store them, e.g. in a struct:
Now, you need to pass the address of your reloc_modifiers structure as the value in R12 for your handler(s) when you register them (or, make sure you can access the structure via whatever address you do have in R12). That way, your assembler veneer can fix-up the stack words before calling the C function.
Here's an example of a fairly general-purpose ATPCS-compatible assmbler veneer for calling a C function at the address is given in R4, parameters are passed in R0-R3.
; R0-R3 = parameters ; R4 -> C function ; Corrupts R0, R14 Generic_Veneer STMFD SP!, {R1-R3, R10-R12, LR} ; Preserve whatever stuff is at the base of the SVC stack... MOV sl, sp, LSR #20 MOV sl, sl, LSL #20 LDMIA sl, {fp, lr} Push "fp, lr" ; Load our C relocation modifiers... LDMIA ip, {ip, lr} MOV fp, #0 ; Store them at the base of the SVC stack... STMIA sl, {ip, lr} ADD sl, sl, #|_Lib$Reloc$Off| ; Branch (with link) into the client function... MOV fp, #0 MOV lr, pc MOV pc, R4 ; Restore the original stuff to the base of the SVC stack... Pull "fp, lr" SUB sl, sl, #|_Lib$Reloc$Off| STMIA sl, {fp, lr} LDMFD SP!, {R1-R3, R10-R12, PC}
Note: |_Lib$Reloc$Off| is a magic number with the value 540.
You're actual IRQ handler might look something like this:
IMPORT C_IRQ_Handler EXPORT irq_handler
irq_handler STMFD SP!, {R0, LR} MOV R0, #some int value MOV R1, #another value ADRL R4, C_IRQ_Handler BL Generic_Veneer CLRV LDMFD SP!, {R0, PC}
and would have a C function prototype like this:
extern void irq_handler(void);
So now you're finally in a position to register the handler:
Words of warning: you'll need to be a C module, of course, because an application may be paged-out when the IRQ is raised. You should also be careful of the fact that your stack chunk is fairly small. All code here is presented as an example rather than being tried and tested.
Hope that helps,
Steve
-- Steve Revill @ Home Note: All opinions expressed herein are my own.
In article <1143856571.700259.26...@u72g2000cwu.googlegroups.com>, <chrisbaz...@bigfoot.com> wrote:
> Jonathan Duddingon wrote: > > Speak registers a RISC_OS "Linear Sound Handler" (SWI &40145) which > Why? Registering a linear sound handler is deprecated in favour of > using SharedSound, which is a true multi-client system that avoids the > race conditions caused by different tasks each attempting to control > the sound system.
Thanks, I was hoping there was a better way. *help sharedsound gives me: Shared Sound 0.58 (15th June 1999)
Where do I find api details of how to use it?
-- change nospam in the reply email address to "jsd"
> In article <1143856571.700259.26...@u72g2000cwu.googlegroups.com>, > <chrisbaz...@bigfoot.com> wrote: >> Jonathan Duddingon wrote:
>> > Speak registers a RISC_OS "Linear Sound Handler" (SWI &40145) which
>> Why? Registering a linear sound handler is deprecated in favour of >> using SharedSound, which is a true multi-client system that avoids the >> race conditions caused by different tasks each attempting to control >> the sound system.
> Thanks, I was hoping there was a better way. > *help sharedsound > gives me: Shared Sound 0.58 (15th June 1999)
In article <4e10b0b090nos...@jsd.clara.co.uk>, Jonathan Duddingon <nos...@jsd.clara.co.uk> wrote:
> > There is some info in the OS StrongHelp. > > http://sudden.recoil.org/stronghelp/ > Sorry, I need more direction. Which of the manuals do I need for > SharedSound information?
It says OS above, so try that one!
BTW, nice to see you around.
Best wishes,
John
-- John Williams, Wirral, Merseyside, UK - no attachments to these addresses! Non-RISC OS posters change user to johnrwilliams or put 'risc' in subject for reliable contact! Who is John Williams? http://www.picindex.info/author/
The "callback" type of handler sounds like it might be similar to the callback that the (Linux) PortAudio library provides.
The handler that I provide has to exit with bit 0 of R3 set to 1. So my handler must be in assembler. However can it immediately call a C function of the type: ?
void MyCallbackHandler(int param, char *start, char *end, int flags)
i.e.
Handler: STMFD r13!,{fp,lr] BL MyCallbackHandler
MOV r3,#1 LDMFD r13!,{fp,pc}
or is it more complicated than that?
-- change nospam in the reply email address to "jsd"
> The handler that I provide has to exit with bit 0 of R3 set to 1. So > my handler must be in assembler. However can it immediately call a C > function of the type: ?
> void MyCallbackHandler(int param, char *start, char *end, int flags)
As Steve outlined in the "Calling C from sound handler" thread it is more complicated than that. That is, unless you take great care in your C code. I have linked C code into an assembler program in the way you outlined above but the C code in question must then be compiled with stack checks switched off (which means you need to make sure by other means that there cannot be a stack overflow) and the C code cannot use any C library functions.
If you want the convenience of the C runtime system and standard library you need to provide the right environment for it in your assembler veneer.
Martin -- --------------------------------------------------------------------- Martin Wuerthner MW Software http://www.mw-software.com/ ArtWorks 2 -- Designing stunning graphics has never been easier spamt...@mw-software.com [replace "spamtrap" by "info" to reply]
In article <fd58c8104e.mar...@bach.planiverse.com>, Martin Wuerthner <spamt...@mw-software.com> wrote:
> > or is it more complicated than that? > As Steve outlined in the "Calling C from sound handler" thread it is > more complicated than that. That is, unless you take great care in > your C code. I have linked C code into an assembler program in the > way you outlined above but the C code in question must then be > compiled with stack checks switched off (which means you need to > make sure by other means that there cannot be a stack overflow) and > the C code cannot use any C library functions.
This sounds worse than I expected. You seem to be saying that unless I know exactly what I'm doing (which I don't) then attempts to use sound in RISC_OS from C are likely to fail.
In Speak v2, my (assembler) Sound Handler set up a transient callback (SWI &54) which directly called a C function, through a line in the cmhgfile (module header file):
irq-handlers: callback_entry/MyCallbackHandler
where int MyCallbackHandler(_kernel_swi_regs *r, void *pw)
is a C function which calls other C functions in the module without worrying about stacks or interrupts. Perhaps I was just lucky that it worked :-)
Isn't the SharedSound "callback" type handler something similar?
> If you want the convenience of the C runtime system and standard > library you need to provide the right environment for it in your > assembler veneer.
Where do I find how to do that?
-- change nospam in the reply email address to "jsd"
On 1 Apr 2006 Jonathan Duddingon <nos...@jsd.clara.co.uk> wrote:
> In article <fd58c8104e.mar...@bach.planiverse.com>, > Martin Wuerthner <spamt...@mw-software.com> wrote: > Isn't the SharedSound "callback" type handler something similar?
> > If you want the convenience of the C runtime system and standard > > library you need to provide the right environment for it in your > > assembler veneer.
> Where do I find how to do that?
I would have thought a CMHG irq veneer or a CMunge generic veneer would surfice.
In article <b62fd1104e.dr...@druck.freeuk.net>, druck <n...@druck.freeuk.com> wrote:
> On 1 Apr 2006 Jonathan Duddingon <nos...@jsd.clara.co.uk> wrote:
> > In article <fd58c8104e.mar...@bach.planiverse.com>, > > Martin Wuerthner <spamt...@mw-software.com> wrote: > > Isn't the SharedSound "callback" type handler something similar?
> > > If you want the convenience of the C runtime system and standard > > > library you need to provide the right environment for it in your > > > assembler veneer.
> > Where do I find how to do that?
> I would have thought a CMHG irq veneer or a CMunge generic veneer would > surfice.
They should do. I don't think Jonathan saw my posting because that's exactly what I explained, if he did want to do it himself.
Steve
-- Steve Revill @ Home Note: All opinions expressed herein are my own.
Jonathan Duddingon wrote: > In article <fd58c8104e.mar...@bach.planiverse.com>, > Martin Wuerthner <spamt...@mw-software.com> wrote: > > > or is it more complicated than that?
> > As Steve outlined in the "Calling C from sound handler" thread it is > > more complicated than that. That is, unless you take great care in > > your C code. I have linked C code into an assembler program in the > > way you outlined above but the C code in question must then be > > compiled with stack checks switched off (which means you need to > > make sure by other means that there cannot be a stack overflow) and > > the C code cannot use any C library functions.
> This sounds worse than I expected. You seem to be saying that unless I > know exactly what I'm doing (which I don't) then attempts to use sound > in RISC_OS from C are likely to fail.
Unless you know what you're doing then writing any kind of code that runs under interrupts is likely to fail. Sound buffer fill handlers are no exception.
> In Speak v2, my (assembler) Sound Handler set up a transient callback > (SWI &54) which directly called a C function, through a line in the > cmhgfile (module header file):
> irq-handlers: callback_entry/MyCallbackHandler
"irq-handlers" was deprecated between versions 5.02 and 5.10 of CMHG, because it was designed for IrqV which is long obsolete. A new type of veneer (keyword "generic-veneers") was added as a replacement for the common use of "irq-handlers" as general purpose hooks onto OS_AddCallBack etc.
> where > int MyCallbackHandler(_kernel_swi_regs *r, void *pw)
> is a C function which calls other C functions in the module without > worrying about stacks or interrupts. Perhaps I was just lucky that it > worked :-)
> Isn't the SharedSound "callback" type handler something similar?
No. The entry and exit conditions are identical to an "immediate"-type handler (and nothing like APCS). I believe you may need a semaphore to prevent re-entrancy if you use a "callback" handler. It is probably called in SVC mode with interrupts enabled (check the documentation).
> > If you want the convenience of the C runtime system and standard > > library you need to provide the right environment for it in your > > assembler veneer.
> Where do I find how to do that?
Here is my attempt at a highly customised veneer to (hopefully) do exactly what you want. In many respects it is similar to the generic veneer already posted on this thread, but should be nicer for this specific purpose.
Your buffer fill function (written in C) should be declared as follows:
(Calling the generic buffer fill routines provided by recent versions of the SharedSound module from within C code is a whole different can of worms that I'm not going to open.)
Here is the assembly language source for the veneer that you should register with SWI SharedSound_InstallHandler. When registering your SharedSound handler you must pass a pointer to your module's private word in R1 (so that it will arrive at the veneer in R0).
The entry point 'old_sharedsound_veneer' is a wrapper for use with versions of the SharedSound module earlier than 1.03. This will allow your fill code to use some extra flags introduced in later versions (which are handy for making optimisations).
old_sharedsound_veneer ; Older versions of SharedSound don't correctly support all flags STR lr,[sp,#-4]! ; push return address
CMP v4,#0 ; is volume 0? ORREQ a4,a4,#(1<<31) ; yes - set mute flag CMN v4,#1 ; is volume &FFFFFFFF? ORRNE a4,a4,#(1<<30) ; no - set 'not full volume' flag
TEQ pc,pc ; Check whether 26 bit or 32 bit mode MOVNE v6,pc ; preserve processor mode in v6 ORRNE ip,v6,#3 TEQNEP ip,#0 ; change to SVC mode (26 bit OS)
MRSEQ v6,CPSR ; preserve processor mode in v6 ORREQ ip,v6,#3 MSREQ CPSR_c,ip ; change to SVC mode (32 bit OS)
STMDB sp!,{v2-v5} ; Push last four arguments of C function onto SVC stack MOV a4,v1 ; registers v1-v5 are now free for reuse
MOV v3,lr ; preserve link register of SVC-mode foreground process ; (R13/sp and R14/lr are private for each processor mode)
MOV sl,sp,LSR #20 ; calculate stack limit (base of the SVC stack MOV sl,sl,LSL #20 ; is always on a megabyte boundary) LDMIA sl,{v1,v2} ; preserve two words at base of SVC stack in v1,v2
LDR a1,[a1,#0] ; get pointer to module's workspace from private word LDMIB a1,{fp,ip} ; get C relocation modifiers from module workspace STMIA sl,{fp,ip} ; store relocation modifiers at base of SVC stack ADD sl,sl,#540 ; increment stack limit so the relocation modifiers ; are at the offset expected by compiled C code
MOV fp,#0 ; zero the frame pointer (otherwise stack backtraces break)
MOV a3,a4 ; Finish marshalling arguments for C function MOV a2,a3 MOV a1,a2 BL sharedsound_handler ; call C function (preserves v1-v6,sl,fp,sp) ; returns updated flags in a1
SUB sl,sl,#540 STMIA sl,{v1,v2} ; restore values originally at base of SVC stack MOV a4,a1 ; must return updated SharedSound flags in R3/a4 not a1
druck wrote: > On 1 Apr 2006 Jonathan Duddingon <nos...@jsd.clara.co.uk> wrote:
> > In article <fd58c8104e.mar...@bach.planiverse.com>, > > Martin Wuerthner <spamt...@mw-software.com> wrote: > > Isn't the SharedSound "callback" type handler something similar?
> > > If you want the convenience of the C runtime system and standard > > > library you need to provide the right environment for it in your > > > assembler veneer.
> > Where do I find how to do that?
> I would have thought a CMHG irq veneer or a CMunge generic veneer would > surfice.
I don't think so, because the veneers generated by CMHG for the "irq-handlers" (deprecated) and "generic-veneers" keywords both expect R12 on entry to point to the module's private word (by which the relocation modifiers are accessed). For a SharedSound handler the user-supplied parameter is instead passed in R1.
In message <4e10caab71nos...@jsd.clara.co.uk> Jonathan Duddingon <nos...@jsd.clara.co.uk> wrote:
> This sounds worse than I expected. You seem to be saying that unless I > know exactly what I'm doing (which I don't) then attempts to use sound > in RISC_OS from C are likely to fail.
^^^^^^^ Interesting spelling.
Anyway, this all seems like a great deal of repeated effort for no obvious gain. If I were you, I would make use of something that already exists. As you've noted, UnixLib has an interface you can directly use from C, and simply throw data at, and as a bonus, will work exactly the same under Liinux. That RISC OS interface uses the DigitalRenderer module, which you could also call the SWIs of directly if you didn't want to use UnixLib.
Peter Naulls wrote: > In message <4e10caab71nos...@jsd.clara.co.uk> > Jonathan Duddingon <nos...@jsd.clara.co.uk> wrote:
> > This sounds worse than I expected. You seem to be saying that unless I > > know exactly what I'm doing (which I don't) then attempts to use sound > > in RISC_OS from C are likely to fail. > ^^^^^^^ > Interesting spelling.
> Anyway, this all seems like a great deal of repeated effort for no > obvious gain. If I were you, I would make use of something that already > exists. As you've noted, UnixLib has an interface you can directly use > from C, and simply throw data at, and as a bonus, will work exactly the > same under Liinux. That RISC OS interface uses the DigitalRenderer > module, which you could also call the SWIs of directly if you didn't > want to use UnixLib.
Except that DigitalRenderer is not itself a multi-user system, nor does it use SharedSound. In my view these are serious deficiencies in a multi-tasking environment.
In message <1143924403.223347.67...@z34g2000cwc.googlegroups.com> chrisbaz...@bigfoot.com wrote:
> Except that DigitalRenderer is not itself a multi-user system, nor does > it use SharedSound. In my view these are serious deficiencies in a > multi-tasking environment.
Fair comment, what do you suggest instead to avoid a reimplementation? ;-)
OTOH, DR's source is in GCCSDK, so anyone could improve it to use SS.
Jonathan Duddingon wrote: > In article <1143856571.700259.26...@u72g2000cwu.googlegroups.com>, > <chrisbaz...@bigfoot.com> wrote: >> Jonathan Duddingon wrote:
>>> Speak registers a RISC_OS "Linear Sound Handler" (SWI &40145) which
>> Why? Registering a linear sound handler is deprecated in favour of >> using SharedSound, which is a true multi-client system that avoids the >> race conditions caused by different tasks each attempting to control >> the sound system.
> Thanks, I was hoping there was a better way. > *help sharedsound > gives me: Shared Sound 0.58 (15th June 1999)
> Where do I find api details of how to use it?
The StrongHelp manuals should give you a decent overview.
I believe that there was also more detailed documentation (with explanations and stuff ;-)), released by ESP, along with a more recent version of SharedSound (1.0X?) which was usable on all machines.
Unfortunately, I can't find a link to it; it doesn't appear to be on the ESP site which is where I thought I'd seen it.
Andrew Hill wrote: > Jonathan Duddingon wrote: > > In article <1143856571.700259.26...@u72g2000cwu.googlegroups.com>, > > <chrisbaz...@bigfoot.com> wrote: > >> Jonathan Duddingon wrote:
> >>> Speak registers a RISC_OS "Linear Sound Handler" (SWI &40145) which
> >> Why? Registering a linear sound handler is deprecated in favour of > >> using SharedSound, which is a true multi-client system that avoids the > >> race conditions caused by different tasks each attempting to control > >> the sound system.
> > Thanks, I was hoping there was a better way. > > *help sharedsound > > gives me: Shared Sound 0.58 (15th June 1999)
> > Where do I find api details of how to use it?
> The StrongHelp manuals should give you a decent overview.
> I believe that there was also more detailed documentation (with > explanations and stuff ;-)), released by ESP, along with a more recent > version of SharedSound (1.0X?) which was usable on all machines.
I have version 1.04 (22 Mar 2002) in !System.310.Modules - I suspect this is the version you are thinking of. It is not 32 bit compatible. I believe that newer versions are only available from RISCOS Ltd.
> Unfortunately, I can't find a link to it; it doesn't appear to be on the > ESP site which is where I thought I'd seen it.
> Anyone care to oblige?
I have two copies of the SharedSound functional specification, one of which describes itself as 'Issue 3, 26 Sep 1999, Authors Andy Pierson / David Lenthall, (C) ESP Music' and the other describes itself as 'Issue 1, 03-Jun-2001, Authors Andy Pierson / Robin Watts'. The latter says 'This revised document is intended to supplant all previous documents by clearly defining what actually is implemented, and what is planned for the future.'
Since my Google search yesterday turned up neither of these documents, perhaps I should make the more up-to-date one publically available on my web site (with the authors' permission of course).
In message <1143982322.256928.144...@j33g2000cwa.googlegroups.com> chrisbaz...@bigfoot.com wrote:
> > Unfortunately, I can't find a link to it; it doesn't appear to be on the > > ESP site which is where I thought I'd seen it.
> > Anyone care to oblige?
> I have two copies of the SharedSound functional specification, one of > which describes itself as 'Issue 3, 26 Sep 1999, Authors Andy Pierson / > David Lenthall, (C) ESP Music' and the other describes itself as 'Issue > 1, 03-Jun-2001, Authors Andy Pierson / Robin Watts'. The latter says > 'This revised document is intended to supplant all previous documents > by clearly defining what actually is implemented, and what is planned > for the future.'
It's about time all these disparate API specifications were collated into a central resource - it's pretty tedious to have to plough through Google search results for $API.