The way is to use the appropriate ALSA library functions as mentioned in the associated docs, and see referenced examples for an outline how the flow is authoritatively supposed to look like, right from the tap.
Please elaborate "weird results for some reason" with minimal examples, as in "this is what I get running this code, and that is what I expected". More often than not, the process of writing up your problems for external review leads to understanding, or at least to a couple good ideas what you might be doing wrong, or expecting to work differently.
The ALSA API is dense, and very C. It's super-easy to make wrong assumptions about how things should work there. Great training for slogging through API docs, though. :)