Version 50.0 - 1.4.2004
audio.device solution for the MorphOS operating system
Developed by Emanuele Cesaroni of Nexus Development /\//)
(url = http://xoomer.virgilio.it/nexusdev/nexusdev/)
How this works
purpose of this device is to make fully compatibles with MorphOS all
programs written in the past using the native audio.device which was
interact with the hardware audio chips of the old 68k Amigas. This PPC
version of the audio.device redirects the commands to the AHI device
use the last generation of sound boards supported by the ahi system.
foresees all the audio.device's original commands: CMD_CLEAR,
CMD_READ, CMD_RESET, CMD_START, CMD_STOP, CMD_UPDATE, CMD_WRITE,
ADCMD_FINISH, ADCMD_FREE, ADCMD_LOCK, ADCMD_PERVOL, ADCMD_SETPREC and
ADCMD_WAITCYCLE. I advice you to read this guide to be informed about
you are using is still under development, so isn't in the final form.
project's roadmap foresees to improve the device in the next releases.
get the version device's number simply typing on shell:
"any_prompt> version devs:audio.device"
You will get a string as "audio.device xx.y" where xx is the version and the y the revision. Starting from version 50.0 dated october 2003 the code is fully PPC compiled.
need MorphOS running and a bit of harddisk space (about 40 KBytes) in
system's partition. AHI device in version 4 minimum is strictly needed.
copy the file "audio.device" to the "DEVS:" directory. Each
time you want to update the device with a new version or revision
above passes replacing the "audio.device" file in "DEVS:".
Take care that after the first device use it could be loaded in ram
becomes resident. So to use the new installed one, when the old has
just only once, you need to reboot the whole system.
device could be configured trought some global variables placed in
In absence of them default values are used. The "default values" point
to a configuration which is the closest possible to the original
behaviour. The default value is used always when the relative global
var is not
found. Moreover some of them must stay under certain numeric intervals.
them are read at audio.device startup (exec.library/OpenDevice()) and
change until the device is not closed (exec.library/CloseDevice()).
explaination of the available ones.
MINPERIOD (1 <= x <= 124)
This informs the audio.device about which period value use as minimum when reproducing the samples. The default value is 124, because it was the original minimum hardware limit imposed by Paula. Many programs, in certain circumstances, use to ask for lower values (Frogger is an example) so to get a good audio ouptut, even in these cases, this configuration input is provided. Read the compatibility list where you can find some infos for each program tested and the "Emulation approach" section of this guide for more details.
To get the MINPERIOD global var to 124, type on shell:
any_path:> setenv "env:audio.device/MINPERIOD" 124
Then copy it/them to envarc: to save it/them at each boot, type on shell:
any_path:> makedir envarc:audio.device
any_path:> copy env:audio.device to envarc:audio.device
The value can be equal or greater than 1 as minimum and equal or lower than 124 as maximum.
How this works
audio.device when is opened for the first time performs these
1) Creates a dos process (an exec superset slave task) which is responsable of all ahi.device calls and is named "NexusDEV slave audio" (in version 50.0 with 127 as priority).
2) The slave process opens ahi.device and setups 4 message ports each one used for each audio unit (from 0 to 3) to receive the CMD_WRITEs commands.
So, for example, if a task opens the audio.device and wants to play a sample, allocates the wanted channels combination (ADCMD_ALLOCATE) and sends trought the device a CMD_WRITE command to the slave process unit. The slave process converts the incoming audio io request into an ahi one which will be sent to the ahi.device. When AHI returns the slave process returns the audio request to the calling task.
The device uses the AHI_DEFAULT_UNIT (unit 0). To get the best performances from the device in conjunction with AHI set at least to 4 the number of channels field of unit 0 under the AHI main preferences program. The equation is: more channels = better sound quality.
The device uses a sub process to have an asynch behaviour. Its priority is 127, so very hight, to allow it to be fast enought to efficently run the audio. Decreasing its priority during the device's life in the system could cause problems (audio will be stopped, the task will be blocked).
audio.device is thought to be compatible with all the programs written
OS instead banging the hardware. Most coders used to lock (by
channels to access directly to the hardware audio registers. These
not compatible with this device but above all with the entire OS. In
you need of UAE. Refer to the "Compatibility
list" and the "Emulation Approach"
doesn't exist a native audio.device's source code available all the
work done is
based upon an assumption derived from documents about the original
operating method (reverse engineering, no disassembling). For this
reason may be
not compatible and most programs using it may have problems. The
the received reports about its usage in combination with certain
allow to improve the whole project. Read the history log to get infos
known bugs. Please be patient using it!
improve the device are wellcome impressions and reports about its
Please send them writing to me.
Be more precise as possible describing the problem you get, the program
using with, the device version and revision etc. If you are a developer
program which uses the audio.device (and it had always worked well)
very appreciable if you test the app with my device reporting the
some infos more about the approach you had used coding.
The device was written by Emanuele
Cesaroni of Nexus Development. You can find Nexus Development at "http://www.genie.it/utenti/nexusdev".
Many thanks for your support...
The audio.device on the classic Amigas interacts with a physical piece of hardware, so with the well known Paula chip. Instead this enhanced audio.device interacts with AHI. For this reason even if AHI allows better performances the device is forced to be closer to the Paula own performances. This allows a better emulation. This approach and the use of AHI could give problem in certain situations. Here a list of them i found during the development.
1) The min period problem.
On all documents about Paula (as on all hearts'walls) you can read that it supports a period range beetween 124 and 65536 clock's cycles per sample. You can ask less than 124 or more than 65536 but without get effects. This is an hardware limit which could not be surpassed. Even if AHI could supports very lower period values i forced the device to work (as default) with 124 as minimum value. So if some coders, in their programs, asked for values < 124 they won't be considered. As result the output may be corrupted. You are allowed to config the minimum period trought an envarc: global variable. Please read the "Configuration" section of this document about the MINPERIOD variable.
2) The AHI performances
AHI is an audio layer. So each time a task wants to play a sample AHI library is called before the sound wave is sent to the audio board's chips. This is the way. For this reason, the coding approach must consider that is better to send longer audio streams few times in a second than sending shorter audio streams many times per second. The old Paula chip had better performances in the second case. The narrator.device is an example. To reproduce the sound it sends to the Paula (trought the audio device) very short samples, in stereo, a lot of times per second. AHI, even used in low level api, is not able to reproduce the audio at a reasonable speed. So in most cases the audio is not outputted. This is a limit, which may be fixxed only by faster AHI versions, or maybe on faster audio devices. Taken from the AHI developer documentation (consider the unroll samples technique for the audio.device is not possible; it is a real time audio processor layer!):
"Also note that playing very short sounds will be very CPU intensive, since there are many tasks that must be done each time a sound has reached its end (like starting the next one, calling the SoundFunc, etc.). Therefore, it is recommended that you "unroll" short sounds a couple of times before you play them. How many times you should unroll? Well, it depends on the situation, of course, but try making the sound a thousand samples long if you can. Naturally, if you need your SoundFunc to be called, you cannot unroll."
programs here listed were tested with the device. Their behaviour had
regular in all circumstances. The tests were done as deep as possible
considering my aknowledgement with them. Where you found a ! you can
infos more about how it works.
- AmigaOS v3.5 own sound preferences program (sound.datatype 40.6)
- AmigaOS v3.1 own sound preferences program (sound.datatype 40.6)
- Amigenerator v0.34
! The audio works but you heard a wait noise in the background. The only way to bypass the problem is to run the program with the NOPSG option enabled.
- Delitracker v2.32
! The program opens the audio.device to get the channels but after a CMD_LOCK it bangs the hardware and then dies. You can also exit safetly from it without playing nothing.
- DirectoryOpus v4.12
- DoomAttack 68k v1.10
! The audio is ok but the video can't work properly on my machine.
- FroggerNG (68k and MorphOS versions)
! Playing some videos the audio seems slow. This is due to the "Min period problem" about what you can read in the "Emulation Approach" section. I saw that playing a wmv stream it asked for a period of 80. So, in this case, this is the minimum value i advice for the global var "envarc:audio.device/MINPERIOD".
- MAME v0.34.3 (tested with very few roms)
- Miami v3.0d (sound.datatype 40.6)
- MooVID v1.2 player on AmigaOS v3.5
- Multiview 45.9 (sound.datatype 40.6)
- narrator.device v37.7
! The narrator.device uses to send tons of requests (CMD_WRITES) to the Paula chip trought the audio.device. The problem is that AHI actually can't support this amount of short calls. AHI is a software layer so works better when the requests are few and longer and worse when are many and shorter. Read the "Emulation approach" section of this guide for more details.
- Payback 68k
- Ports of Call (game)
- Prayer v2.0
! Not totally supported (needs a small change in sources) because bangs the hardware.
- PuzzleBOBS game v0.750 (in all its audio output modes)
! It asks 0 as period, so pay attention to your MINPERIOD global varfile configuration. In this case MINPERIOD = 124 is the adviced value to use.
- Say and Saymore
! See narrator.device in this section.
- Samplitude Opus v3.5
- SongPlayer v1.4
! It opens regularly the device to get the channels but then bangs the hardware.
- WBClock v45.10 (sound.datatype 40.6)
- YAM v2.3p1 (sound.datatype 40.6)
- Xgb (Game boy emulator)
Some commands as ADCMD_WAITCYCLE had never been tested by external apps
rare they are used). They have been tested succesfully under the
own test program only.
2) The device's init function probably touchs some register it shouldn't. Some programs (ADoom for example) at first audio.device opening, stops forever after had opened the device. I think is due to a stack or register problem. I am inquiring.
A final extreme experiment on the low level approach had failed. I tried this: At the audio.device first open i alloc a very large mem block for audio buffering. Then i turn on ahi so just at the beginning ahi is always reproducing a sample full of zeros. When an audio request income i copy its data for the requested lenght on the buffer so it starts immediately because ahi was just infinite looping under that mem area. I need just to copy the data and change len and freq. For our ppc processor this should be an easy work considering that this coding way looks like the unrool technique. Unlucky this approach is too extreme and the multitasking may corrupts too much the output. The global behaviour results totally out of controll, there are too many delays and a big noise in the background. Audio wants quality... so in future lets leave the narrator.device where it is... it is a too old piece of software. Its the time to write it again! ;-)
the experimental pieces of code will be removed before the next
(50.0 - 20.3.2004)
Added the configuration layer trought the dos.library/GetVar(). Since today some configuration inputs could be read from some global vars in "env:audio.device/". Actually is supported the MINPERIOD input value only. All the test previously done with the use of the low level api failed. It seems AHI is not enought fast in reproducing the audio when requesting too many commands per second at short lenght. The supporting is still left there. Now is sure that to have a good device reaction to the inputs a process pri of 127 is strictly needed.
(50.0 - 25.2.2004)
Started today a great change to the code tring to fix a problem with the narrator.device. I am replacing the ahi.device use with the ahi low level api protocol in conjunction with the timer.device to count real the sample lenght. Replaced CTR_SIG_BREAKF with the SIGF_DOS signal one for the controll exchange protocoll.
(50.0 - 19.1.2004)
Some small changes to get Delitracker compatible at program starting and exiting. In any case Delitracker bangs the hardware soon after an ADCMD_LOCK and on MorphOS it dies. If you don't play anything the program exits well. Some fixes to the Slave Process init procedure too.
(50.0 - 17.12.2003)
Rewritten a small part of the builtin audio.device command (CMD_CLOSE) thought to die the slave process. A fix now lets the device to work regularly with CMD_WRITE commands with more than one single cycle per wave (ioa_Cycles) as it happens in "Ports of Call" game. Added again some semaphores where they are strictly needed.
(50.0 - 15.11.2003)
After some tests i wrote again the linking protocol between the slave process and the main device unit. Because the slave process **MUST** be synchronized with the device in certain situation were the data sharing model is not allowed i searched for a signal bit number which the slave process could use to unlock the device waiting. The device infact sends the command to the slave process and soon after it waits for a signal while the slave process is touching some structures they can't manage in the same time. When this lapse is ended the device is unlocked trought a signal. But which signal bit number use for this controll exchange? Well, the own IORequest signal is not sufficent when a task sends command from more than one task. This is the example of Wipeout. It has two tasks, one opens the device and waits for the commands end the other sends them only. Reply to the waiting one before the command is end made a lot of confusion to the app which had a task completely locked. An other way i used in the past was to alloc a signal for each Task the device receives command from. So i putted a copy of the pointer of each of them in a list and when a command was received i went to see if a signal was just ready for that task. If it was just allocated i used it for the linking procedure. This was a really big waste of time because at each command i had to do a long reasearch trought the list. So finally i adopted this method which somebody could consider dangerous, but since today it has always worked. Simply when i receive an IORequest i obtain its task pointer. I stole to it the CTRL_SIG_BREAKF signal and then i force it to wait for this signal only. When the controll exchange is done i bring back the task's wait signal set to its initial status. Hope this will work ever!
(50.0 - 2.10.2003)
A very long inactive time on this project. In this new release the device has been re-styled deeply and the version was brought down again to the 50.0. The most important changes of this re-styled version.
No more the FAKE and REAL operating modes difference. Now the device
in REAL mode so it outputs really the audio trought ahi.device which
strictly needed al least in version v4. If it isn't present on the
device fails just in OpenDevice().
2) Erased totally the virtual channels system. Now there are only 4 channels, or better 4 units as the original audio.device had. The units are under the slave process control and each one has a message port thought to receive CMD_WRITEs commands only. All the other commands are received by an other one message port controlled by the slave process again.
3) No more IORequest mirroring but fast message handling between the device and the slave process.
4) Added the original audio.device's double buffering technique. When more than two CMD_WRITEs are sent to the device the first is output, the second is put in a cache the others are inserted in a wait list. This allows to start faster the second wave when the first is ended so the null audio lapse between them is shorter for a better sound quality.
5) Rewritten all the commands functions. Now they are faster. Rewritten AbortIO() which was one of the bigger problem of the past revisions. Now seems very stable and effectively functional.
6) Erased the old link system used to interact with the slave process. Actually is used the IORequest own replyport and signal.
7) Rewritten BeginIO(), OpenDevice() and CloseDevice() internal routines and the slave process main loop totally. Erased a lot of old code and complex procedures. The device now is smaller, simpler and faster.
8) Erased all the semaphores used in BeginIO(), AbortIO() and in the OpenDevice() and CloseDevice() internal functions.
(52.2 - 16.4.2003)
Not a new revision but a lot of few changes in the code to make it faster and more stable.
(52.2 - 10.4.2003)
A lot of improvements on this release. Rewritten TOTALLY AbortIO(). Now a lot of programs which gave problems in the past are working properly. Rewritten CMD_FLUSH and CMD_FINISH. Moreover i modified the process priority. This may be dangerous but since i increase it all the programs under testing are working better. The priority now is 127. Because the original audio.device worked trought hardware interrupts is clear that a software device needs to be faster as possible in replying to the programs.
(52.1 - 10.4.2003)
Modified the AHI starter. Actually i am using BeginIO() instead of SendIO(). This seems better in certain circustances.
(52.0 - 7.4.2003)
Rewritten ADCMD_PERVOL. Actually it does a lot of usefull things. It modifies on channel the period and volume as the classic audio.device used to do.
(51.9 - 4.4.2003)
Activated again the FAKE mode. It works as well as the REAL mode one. Rewritten some parts of code which were not allowing to enable the -02 GCC optimization.
(51.8 - 2.4.2003)
Rewritten the system which manages, finds, allocs, frees the virtual channels. Actually the channel struct at beginning has a node struct. This allows to move channels between lists without moving data or copying structure fields for each audio output. Actually the exec.library/AllocSignal() not checked is fixxed. When a task opens the audio.device its task's struct address is put in a list. The list contains for the task a just allocated signal and some structs just ready to make faster initializations and slave process message exchanging. Most part of the code was optimized erasing function calls with quick memory array accesses (the case of the count chans routine).
(51.7 - 28.3.2003)
Fixxed the NT_MESSAGE IOAudio node-type problem in BeginIO() so now most programs which use CheckIO() now work (ADoom). Fixxed a bug in ADCMD_ALLOCATE when the task asks for a particular channel key just known. Rewritten ADCMD_PERVOL even if actually it does nothing special more than null. Added in this doc a program compatibility list. Tested with 12 channels and 4 programs at 4 channels for each succesfully (only one didn't exit!).
(51.6 - 22.3.2003)
Rewritten totally the system which manages lists. Verified, under Samplitude Opus, the CMD_STOP and CMD_START. Now they work. Removed the FAKE mode part of code. It will be added again later recycling the REAL mode routines after the needed tests. So in release 51.6 the device works exclusively in REAL mode. The whole is still 68k, not optimized.
(51.5 - 12.3.3003)
Rewritten the exit routines in the slave process. Actually the process is removed from the device itself. Rewritten the device init functions which inits the slave process and an usefull semaphore. The tests under MorphOS actually are going well. No hits and no bad memory accesses.
(51.4 - 02.3.2003)
Fourth release. The device supports definitely AHI. The audio output is functional and good. I tested it with my PuzzleBOBS game and it works. Rewritten the AbortIO() function so most of programs which use it now work. The device now performs less operation during each audio initializing for better performance.
(51.3 - 20.2.2003)
Third release. Added some code for the REAL mode. The slave task actually is a process allowing to open the ahi.device. The system opens AHI if it founds it. If not it swaps into FAKE mode. Actually is ready to work in REAL mode. Moreover the device was tested with 8 channels and two programs asking both for 4 channels. The test was successfull but in this release the number of channels was brought to 4 maximum again. The whole is still GCC 68K compiled without any optimizations. Under MorphOS all the hits to Ramlib are disappear (there were some not allowed memory accesses).
(51.2 - 19.2.2003)
Fixxed the message link system beetween slave task and audio.device with the use of exec.library/AllocSignal() and exec.library/FreeSignal(). The whole is now faster and the major problems of the second release seem solved. The problem about the bad count period now is fixxed even if it result a bit longer than the real audio.device one. This time difference increases when there are more than one cycle for wave. That is due to the work done by the slave process which loses time initialiting again the timer.device each cycle. The optimization of the slave process main code in conjunction with the adoption of the ppc code should reduce the problem. This version wont be released.
(51.1 - 15.2.2003)
Second release. Some bugs were removed and the whole is improved. Actually at opening and closing (exec.library/OpenDevice() and exec.library/CloseDevice()) the problems present in the revision 0 are fixxed. Some RamLib's hits, but no gurus. All the resources are freed and generally the whole seems working well. The bad count period is already present and sometimes when two task open it at the same time, one of them results locked at opening and the other at closing.
(51.0 - 11.2.2003)
First release. The device is ready but needs to be deeply tested. Actually is 68k, supports only 4 channels and works in FAKE mode. Sometimes it crashes. If you run the test program from shell add some mem to stack before. This may rend it more stable.
All of the files in
this archive are
Copyright 2003 Nexus Development of Emanuele Cesaroni. The
contents of this
archive are protected by Copyright laws and Nexus Development reserves
The contents of this archive are protected by Copyright laws and Nexus Development reserves allof the rights on the files. It's forbidden to alter any of the files in this archive in any way and/or to modify the archive itself. In no event shall Nexus Development liable for any direct or indirect damages arising out of the use of the files in this archive. Redistribution of this archive in part or in its entire form is permitted.