Login
Username:

Password:

Remember me



Lost Password?

Register now!

Sections

Who's Online
93 user(s) are online (77 user(s) are browsing Forums)

Members: 0
Guests: 93

more...

Support us!

Headlines

 
  Register To Post  

AHI & Multi sound output.
Quite a regular
Quite a regular


See User information
Hi,

I have a small sample that I received from a member of the forum that can play 1 sample under AHI ...

but, I'm not sure about how I can adapt it to be able to play at the same time more than 1 sound.

Here is the source code :

ahi_sounds.h :
char *snd_buffer[5];
int sound_file_size[5];

int number;

struct Process *sound_player;
int sound_player_done 0;

void load_sound(char *nameint number){
  
FILE *fp_filename;
  if((
fp_filename fopen(name,"rb")) == NULL){
    
printf("can't open sound file\n");exit(0);
   };
  
fseek (fp_filename,0,SEEK_END);
  
sound_file_size[number] = ftell(fp_filename);
  
fseek (fp_filename,0,SEEK_SET);
  
snd_buffer[number]=(char *)malloc(sound_file_size[number]);
  
fread(snd_buffer[number],sound_file_size[number],1,fp_filename);
  
fclose(fp_filename);
 }

void play_sound_routine(void){
  
struct MsgPort    *AHImp_sound     NULL;
  
struct AHIRequest *AHIios_sound[2] = {NULL,NULL};
  
struct AHIRequest *AHIio_sound     NULL;
  
BYTE               AHIDevice_sound = -1;
  
//ULONG sig_sound;

  //-----open/setup ahi
  
if((AHImp_sound=CreateMsgPort()) != NULL){
    if((
AHIio_sound=(struct AHIRequest *)CreateIORequest(AHImp_sound,sizeof(struct AHIRequest))) != NULL){
      
AHIio_sound->ahir_Version 4;
      
AHIDevice_sound=OpenDevice(AHINAME,0,(struct IORequest *)AHIio_sound,0);
     }
   }
  if(
AHIDevice_sound){
    
Printf("Unable to open %s/0 version 4\n",AHINAME);
    goto 
sound_panic;
   }
  
AHIios_sound[0]=AHIio_sound;
  
SetIoErr(0);
  
AHIios_sound[0]->ahir_Std.io_Message.mn_Node.ln_Pri 127;
  
AHIios_sound[0]->ahir_Std.io_Command  CMD_WRITE;
  
AHIios_sound[0]->ahir_Std.io_Data     snd_buffer[number];//sndbuf;
  
AHIios_sound[0]->ahir_Std.io_Length   sound_file_size[number];//fib_snd.fib_Size;
  
AHIios_sound[0]->ahir_Std.io_Offset   0;
  
AHIios_sound[0]->ahir_Frequency       8000;//44100;
  
AHIios_sound[0]->ahir_Type            AHIST_M8S;//AHIST_M16S;
  
AHIios_sound[0]->ahir_Volume          0x10000;          // Full volume
  
AHIios_sound[0]->ahir_Position        0x8000;           // Centered
  
AHIios_sound[0]->ahir_Link            NULL;
  
DoIO((struct IORequest *) AHIios_sound[0]);
sound_panic:
  
//printf("are we on sound_exit?\n");
  
if(!AHIDevice_sound)
    
CloseDevice((struct IORequest *)AHIio_sound);
  
DeleteIORequest((struct IORequest *)AHIio_sound);
  
DeleteMsgPort(AHImp_sound);
  
sound_player_done 1;
 }

void stop_sound(void){
  
Signal(&sound_player->pr_TaskSIGBREAKF_CTRL_C );
  while(
sound_player_done !=1){};
  
sound_player_done=0;
 }

void play_sound(int num){
  
number=num;
  
sound_player CreateNewProcTagsNP_Entry, &play_sound_routine,
                                    
NP_Priority1,
                                    
NP_Name"Ahi raw-sound-player Process",
                                    
TAG_DONE);
  
Delay(10); // little delay for make sounds finish
 
}


and play_ahi_raw.c :
// os4 define
#define __USE_INLINE__ 1

// system includes:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/ahi.h>

// our routines include:
#include "ahi_sounds.h"


// main code.

main()
{

load_sound("PROGDIR:sounds/flip.raw",0);
load_sound("PROGDIR:sounds/wrong.raw",1);
load_sound("PROGDIR:sounds/click.raw",2);


play_sound(0);
Delay(50);

play_sound(1);
Delay(50);

play_sound(2);
Delay(50);

stop_sound();

free(snd_buffer[0]);
free(snd_buffer[1]);
free(snd_buffer[2]);

}


In fact, this sample play sample 0, wait it finish, play sample 1, wait it finish, play sample 2.

Now, I'm not sure if :
1. I must create 1 process per sound played at the same time or, can I use the same process to play more than 1 sample at the same time ?
Can someone help me ?

Thank you.

Regards,
AmiDARK.

All we have to decide is what to do with the time that is given to us.
Go to top
Re: AHI & Multi sound output.
Home away from home
Home away from home


See User information
@freddix
I usually create new process for every sound and every music track. Dunno still how good that way is :)

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top
Re: AHI & Multi sound output.
Quite a regular
Quite a regular


See User information
@kas1e
Ok
Thank you.

Will try this ;)

EDIT : Is it possible to create the Proc with arguments like the sound sample ID to play ?


Edited by freddix on 2010/6/9 15:02:31
All we have to decide is what to do with the time that is given to us.
Go to top
Re: AHI & Multi sound output.
Home away from home
Home away from home


See User information
@freddix

I can show example of how i use it with PTPlay.library (For open mods , decoding them by PtPlay.library and playing over AHI over new process).

Code is ugly and alt, but you will see the main idea imho.

So, i have fucntion called Play_Module(name) , where name is path to the module. That function looks like this:

BOOL play_module(CONST_STRPTR name_of_module)

{
 
  
//-----read file to memory-----

    
fp_mod_filename Open(name_of_module,MODE_OLDFILE);
    if(
fp_mod_filename==0) {
        
printf("can't open module\n");
        goto 
corozia;
    };

    
ExamineFH(fp_mod_filename, &fib);

    
modbuf malloc(fib.fib_Size); if(modbuf == NULL) { printf ("can't malloc for module\n"); goto corozia;};

    if (
modbuf)
    {
        
Read(fp_mod_filenamemodbuffib.fib_Size);

    }

    
Close(fp_mod_filename);

//---------


    
type PtTest(name_of_modulemodbuf1200);

    if(
type == TRUE)  { };
    if(
type == FALSE) { Printf ("this module suck!\n"); goto corozia;};

    
modptr PtInit(modbuffib.fib_Sizefreqtype);
 

            
player CreateNewProcTags(
                            
NP_Entry, &play_module_routine,
                            
NP_Priority1,
                            
NP_Name"Player Process",
                                      
TAG_DONE);
  
   return 
TRUE;

corozia:
   if(
modbuffree(modbuf);
   
printf("somethink going wrong whyle trying to crate mod_player process!\n");
   return 
FALSE;

}


In that fucntion i handle all the crap like open/read module, and create a new process. New process fucntion looks like this:

static void play_module_routine(void)
{



  
struct MsgPort    *AHImp     NULL;
  
struct AHIRequest *AHIios[2] = {NULL,NULL};
  
struct AHIRequest *AHIio     NULL;
  
APTR               AHIiocopy NULL;
  
BYTE               AHIDevice = -1;

  
char *buf1, *buf2;
  
ULONG sig;
  

    
//-----open/setup ahi

    
if((AHImp=CreateMsgPort()) != NULL) {
    if((
AHIio=(struct AHIRequest *)CreateIORequest(AHImp,sizeof(struct AHIRequest))) != NULL) {
      
AHIio->ahir_Version 4;
      
AHIDevice=OpenDevice(AHINAME,0,(struct IORequest *)AHIio,0);
    }
  }

  

  if(
AHIDevice) {
    
printf("Unable to open %s/0 version 4\n",AHINAME);
    goto 
cleanup;
  }




     
// Make a copy of the request (for double buffering)
  
AHIiocopy AllocMem(sizeof(struct AHIRequest), MEMF_ANY);
  if(! 
AHIiocopy) {
   
printf("can't do AllocMem for AHIiocopu\n");
   goto 
cleanup;

  }
  
CopyMem(AHIioAHIiocopysizeof(struct AHIRequest));
  
AHIios[0]=AHIio;
  
AHIios[1]=AHIiocopy;

  
SetIoErr(0);

//-----------
   
    
buf1=malloc(size_of_block*num_of_blocks); if(buf1 == NULL ) { printf ("sorry, can't malloc for ahi_buf1\n"); goto cleanup;};
    
buf2=malloc(size_of_block*num_of_blocks); if(buf2 == NULL ) { printf ("sorry, can't malloc for ahi_buf2\n"); goto cleanup;}


    
PtRender(modptrbuf1buf1+offset_bytenum_of_blockssize_of_block1bit_depthnum_channels);
    
PtRender(modptrbuf2buf2+offset_bytenum_of_blockssize_of_block1bit_depthnum_channels);

    
AHIios[0]->ahir_Std.io_Message.mn_Node.ln_Pri priority;
    
AHIios[0]->ahir_Std.io_Command  CMD_WRITE;
    
AHIios[0]->ahir_Std.io_Data     buf1;
    
AHIios[0]->ahir_Std.io_Length   size_of_block*num_of_blocks;
    
AHIios[0]->ahir_Std.io_Offset   0;
    
AHIios[0]->ahir_Frequency       freq;
    
AHIios[0]->ahir_Type            ahi_type;
    
AHIios[0]->ahir_Volume          0x10000;          // Full volume
    
AHIios[0]->ahir_Position        0x8000;           // Centered
    
AHIios[0]->ahir_Link            NULL;
    
SendIO((struct IORequest *) AHIios[0]);


    
AHIios[1]->ahir_Std.io_Message.mn_Node.ln_Pri priority;
    
AHIios[1]->ahir_Std.io_Command  CMD_WRITE;
    
AHIios[1]->ahir_Std.io_Data     buf2;
    
AHIios[1]->ahir_Std.io_Length   size_of_block*num_of_blocks;
    
AHIios[1]->ahir_Std.io_Offset   0;
    
AHIios[1]->ahir_Frequency       freq;
    
AHIios[1]->ahir_Type            ahi_type;
    
AHIios[1]->ahir_Volume          0x10000;          // Full volume
    
AHIios[1]->ahir_Position        0x8000;           // Centered
    
AHIios[1]->ahir_Link            AHIios[0];
    
SendIO((struct IORequest *) AHIios[1]);



    for(;;)
    {
   

            
sig Wait(SIGBREAKF_CTRL_C << AHImp->mp_SigBit);

            if (
sig SIGBREAKF_CTRL_C)
                 break;


            
WaitIO((struct IORequest *) AHIios[0]);

            
PtRender(modptrbuf1buf1+offset_bytenum_of_blockssize_of_block1bit_depthnum_channels);

            
AHIios[0]->ahir_Std.io_Message.mn_Node.ln_Pri priority;
            
AHIios[0]->ahir_Std.io_Command  CMD_WRITE;
            
AHIios[0]->ahir_Std.io_Data     buf1;
            
AHIios[0]->ahir_Std.io_Length   size_of_block*num_of_blocks;
            
AHIios[0]->ahir_Std.io_Offset   0;
            
AHIios[0]->ahir_Link            AHIios[1];
            
SendIO((struct IORequest *) AHIios[0]);

            
WaitIO((struct IORequest *) AHIios[1]);

            
PtRender(modptrbuf2buf2+offset_bytenum_of_blockssize_of_block1bit_depthnum_channels);

            
AHIios[1]->ahir_Std.io_Message.mn_Node.ln_Pri priority;
            
AHIios[1]->ahir_Std.io_Command  CMD_WRITE;
            
AHIios[1]->ahir_Std.io_Data     buf2;
            
AHIios[1]->ahir_Std.io_Length   size_of_block*num_of_blocks;
            
AHIios[1]->ahir_Std.io_Offset   0;
            
AHIios[1]->ahir_Link            AHIios[0];
            
SendIO((struct IORequest *) AHIios[1]);
      };

    
// Abort any pending iorequests
  
AbortIO((struct IORequest *) AHIios[0]);
  
WaitIO((struct IORequest *) AHIios[0]);

cleanup:

  if(!
AHIDevice)
  
CloseDevice((struct IORequest *)AHIio);
  
DeleteIORequest((struct IORequest *)AHIio);
  
FreeMem(AHIiocopy,sizeof(struct AHIRequest));
  
DeleteMsgPort(AHImp);

  if(
buf1)free(buf1);
  if(
buf2)free(buf2);

  
player_done 1;

}


In that function exactly depacking and plaing of modules in loops happenes. Code are ugly of course, for sure WaitIO and alt are using there wrong, but it works and you can catch main idea here (how create a process with passing to it name of music file).

Hope that help

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top
Re: AHI & Multi sound output.
Quite a regular
Quite a regular


See User information
@kas1e
if I'm right,

- 1 st Question :
with this :
struct AHIRequest *AHIios[2] = {NULL,NULL};

I define 2 sample at the same time

so if I set :
struct AHIRequest *AHIios[8] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};


and if I define all 8 samples like you did, it should allow to play 8 samples at the same time ?

More to this,

- 2 nd Question :
Imagine I have 1 sample running and I want to add 1
I do not need to define a new proc but I can define values needed for the new song and use :
SendIO((struct IORequest *) AHIios[1]);

to start playing the sound ?

And then, I'll remove the proc when no sound is played or when my app quit . Right ?

- 3rd Question :
Another question, can I define a new sound out from the proc itself ? or should it be the proc itself that define the sound ?
(for exemple initialize a new proc that run in background and define new sound when needed)

- 4th Question :
Can I stop a sound from playing ? at any moment ?

Thank you for everything.

Kindest Regards,
Freddix aka AmiDARK.

All we have to decide is what to do with the time that is given to us.
Go to top
Re: AHI & Multi sound output.
Just can't stay away
Just can't stay away


See User information
@freddix

The MissCmd source code (a missile command clone that uses P96/AHI) has some easy to use audio routines that should do more or less what you want.

Go to top
Re: AHI & Multi sound output.
Home away from home
Home away from home


See User information
@freddix

- 1 st Question : Its more not about "samples" itself, its about reserving the ahi IO structs. It can be for the small buffer data, or for big one. You also can redefine it with not problems (for example, you play one sound, then you close ahi and alt, and for second sound, you can use the same routine).

I use 2 IO strcuts-buffers just because i need 2 buffers in my player_routine (for making double-buffering). It possible of course make everythinkg with 1 IO, or with 10IO (as you wish).

So it not about plaing at one time, but about just reserving the same twice for double-buffering (for avoid sutterings beetwen parts of data).

- 2st Question: Yes, if you not close older resources, you not need to open it again, and just adding IO will be ok.

- 3st Question: I do not remember right what happenes when you will be remove you Process from memory in hardcore way, but by logic, if you will remove it hardcore it will stops all works of course. That how looks my Stop_Play() fucntion:

void stop_module(void)
{

     
Signal(&player->pr_TaskSIGBREAKF_CTRL_C );
     while(
player_done !=1){};
     
PtCleanup(modptr);
     if(
modbuffree(modbuf);
     
player_done=0;
}


You send signal to your process (and you need to check always on that signal in your main player routine), and when it return that everything end, then stop everythink/clean/exit/close/etc. You can see that logic of my fucntions are bad. I.e. i put for example code for cleaning/close/remove ahi reqst/dev to the player routine (it just was more easy for my brains). But in general you need prepare normal fucntions for open/play/close.

-4st question: Yes, just by sending signal SIGBREAKF_CTRL_C to your player process (and you need to check it all the time while music plays in your player routine).

That of course only about how i do that. For sure its lame and wrong :)

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top
Re: AHI & Multi sound output.
Quite a regular
Quite a regular


See User information
@freddix

What essentially makes this routine "single-tasking" is the DoIO() call. If you replace this for SendIO() the function would return immediately while the sound is playing and you could start another sound the same way.

Then you Wait() on the signals from all iorequests you have sent and take care of them (DeleteIO etc) one at a time when they are done.

Of course you have to rewrite your play function such that it doesn't free everything at the end but instead keeps the state (using globals instead of locals?) so you can free it all later.

In this case I would actually suggest swapping to another language, such as C++ or PortablE and create a proper class which handles your plaing. Then just create as many instances as you like, encapsulate everything and coordinate it all from a Wait(class1.signal | class2.signal | class3.signal) or something in the main program event loop. No need for processes.

Software developer for Amiga OS3 and OS4.
Develops for OnyxSoft and the Amiga using E and C and occasionally C++
Go to top
Re: AHI & Multi sound output.
Quite a regular
Quite a regular


See User information
@Deniil
Thank you for your comment.
Concerning the functions it confirm what I suspected ;)
I will start this tomorrow.

Concerning the AmiDARK Engine, I will remain under C... No need for C++ ... I found the C++ classes and others stuffs complicated to do thing I found to be more easier without these classes system ..

It's simply I have used to code this way during several years ... It will probably need many months for me to adapt to C++ so .... no C++ for the moment

Thank you all for your comment
I should be able to do my sound functions now :)

@ +
AmiDARK.

All we have to decide is what to do with the time that is given to us.
Go to top
Re: AHI & Multi sound output.
Home away from home
Home away from home


See User information
@freddix

So next version of DarkEngine will be with music/sound support ? :) Will be cool also to have Sync-music functions (like getting the bass details, volume details, and with basing on it can be done pretty good visual effects).

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top
Re: AHI & Multi sound output.
Quite a regular
Quite a regular


See User information
@kas1e
The next alpha may be released soon (before completing sound plugin (sound is only load/Delete/clone/play/loop audio sounds WAV/MP3/OGG/RIFF/.... it's not music plugin) or later when sound plugin is done.
Music plugin will came later ;)
Concerning sound track informations, all will depend on the library I'll find that allow to play tracker files ... I will not try to recreate the wheel by creating my own music support so, all will depend on the library I'll use ... If you have any suggestion feel free to post them ;)

All we have to decide is what to do with the time that is given to us.
Go to top
Re: AHI & Multi sound output.
Home away from home
Home away from home


See User information
@freddix

SDL_mixer / Mikmod and ModPlug imho are easy for usage on aos4 for mp3/ogg and alt modules like xm/mod/it. But that libs does not have any good functions for getting info about music (well, its imho, i not research it very deeply). Sadly that we do not have FMOD. FMOD have pretty nice functions like:

FSOUND_DSP_SetActive(FSOUND_DSP_GetFFTUnit(), true);
float *spectrumData=FSOUND_DSP_GetSpectrum();


Of course implementing own sound-engine which will grab all the info are pretty hard .. (imho). But that sync-with-music functions can allow to create quality animation/demos.

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top

  Register To Post

 




Currently Active Users Viewing This Thread: 2 ( 0 members and 2 Anonymous Users )




Powered by XOOPS 2.0 © 2001-2024 The XOOPS Project