johnsa wrote:
...the approach we've probably all used is a generic widget enumeration...
I think it's the only sane option for an individual writing an OS who doesn't want to spend all their time writing drivers. The most important thing is just to get sound to speakers and/or headphones, plus volume control for each, and that isn't too hard to do. Some may be connected up in such a way that you can either use speakers or headphones and not both at once, but I suspect most put them on different pins with independent volume controls while allowing them to get input from the same or different DACs. Microphone sockets are disappearing, which means we should write USB audio drivers for sound input instead (or just rely on a built-in microphone, which is far from ideal, or use the headphone socket for the microphone and be forced to use the speakers for sound output). That push towards further reliance on USB makes the idea of spending a lot of time on drivers for individual hda codecs less attractive, unless something very specific needs to be done to get a particular type working.
Quote:
That's the first page I've seen anywhere that gives any clue as to how to set vref for microphones.
The big priority though is just to get sound output so that blind people can use some kind of speech synthesis up and running. That speech synthesis needn't sound great, but merely be intelligible. I will be happy to help build that with them.
Ethin wrote:
how would I actually play audio streams?
That's the easiest bit as you can just write wav file content into the buffer. If you've loaded an entire sound file into memory in wav form (minus the header), you can simply make that the buffer and the dma engine will run through it over and over again until you tell it to stop. If you want to save space, you could use a ten second buffer and set a timer to maintain its content every few seconds, loading new data into it far ahead of the current read position. There's no great pressure on the software to keep up with this, which is why using hda interrupts isn't necessary. The only kind of thing you might need to do in a hurry is make warning beeps, and that doesn't need interrupts: you just need to write as close to the current read position as you can without being overtaken by the dma engine. You can hear Windows get this wrong sometimes when the start of a sound is missing because it was written too close to the read position.
If your OS is keeping well on top of everything, your buffer could be under a second in length, and it maybe should be that short. If you're playing a music track, you should be copying small chunks of it from elsewhere in memory to it on a regular and frequent basis. If there's additional sound data needing to be played simultaneously, that data may only be generated a moment before it needs to be played, and it should in theory be more efficient to add it to the data from the main sound track and write the result into the buffer that the dma is reading rather than writing the main track to that buffer in advance and then adding the extra sounds to it there. The difference may be insignificant though: the latter approach would involve copying data to the buffer, some of which will then need to be replaced, and adding the other sound track to it involves the processor dragging data back from the buffer to add the new data and then writing the result back to the buffer. It'll collect it from the closest cache though, so it'll still be quick if the cache doesn't have to be reloaded. There is a big advantage with the latter approach though as the sound track will keep playing for longer if something goes wrong. Indeed, I can have a sound file go on playing while my OS switches back into real mode to use the BIOS to load data from (or save data to) a flash drive. (That isn't a capability that my OS will need once I have working USB drivers, but it illustrates what's possible.) However, nothing should be going wrong: there should be a regular timer interrupt triggering a process into making sure the buffer holds enough content to last beyond the next such interrupt.