static int
MaxPlaySamples(ULONG mode_id, ULONG mix_freq, ULONG player_freq) {
  int rc = RETURN_OK;

  struct AHIAudioCtrl* actrl = AHI_AllocAudio(AHIA_AudioID,       mode_id,
					      AHIA_MixFreq,       mix_freq,
					      AHIA_PlayerFreq,    player_freq << 16,
					      AHIA_MinPlayerFreq, player_freq << 16,
					      AHIA_MaxPlayerFreq, player_freq << 16,
					      AHIA_Channels,      1,
					      AHIA_Sounds,        1,
					      TAG_DONE);

  if (actrl != NULL) {
    ULONG max_play_samples = 0;

    if (AHI_GetAudioAttrs(AHI_INVALID_ID, actrl,
			  AHIDB_MaxPlaySamples, &max_play_samples,
			  TAG_DONE)) {
      fprintf(stderr, 
	      "MaxPlaySamples for mode 0x%08lx (Fsample = %ld Hz, Fplayer = %ld Hz) is %ld\n",
	      mode_id, mix_freq, player_freq, max_play_samples);
    }
    else {
      fprintf(stderr, "Unable to get MaxPlaySamples.\n");
      rc = RETURN_ERROR;
    }
    AHI_FreeAudio(actrl);
  }
  else {
    fprintf(stderr, "Unable to allocate audio.\n");
    rc = RETURN_ERROR;
  }

  return rc;
}
Exemple #2
0
VOID DispatcherThread(struct MOSWriteHandle* h)
{
	struct MsgPort*	  ahi_port = NULL;
	struct AHIRequest*  ahi_request = NULL;
	struct AHIAudioCtrl*ahi_control = NULL;
	BYTE*					  sample_bufs = NULL;
	ULONG					  sample_size = 2;
	BYTE					  ahi_device = -1;
	LONG					  switch_sig_bit = -1;
	LONG				     locked_buf = -1;
	struct DispatcherStartupMsg *startup_msg;
	struct DispatcherInitReport *init_report;
	struct MsgPort     *task_port = NULL;
	struct ExecBase *SysBase = *(struct ExecBase **) 4;

	init_report = (struct DispatcherInitReport *) AllocVec(sizeof (struct DispatcherInitReport), MEMF_PUBLIC | MEMF_CLEAR);
	if (init_report == NULL)
		return;

	NewGetTaskAttrsA(NULL, &task_port, sizeof (task_port), TASKINFOTYPE_TASKMSGPORT, NULL);
	NewGetTaskAttrsA(NULL, &startup_msg, sizeof (startup_msg), TASKINFOTYPE_STARTUPMSG, NULL);

	if (task_port == NULL || startup_msg == NULL)
	{
		FreeVec(init_report);
		return;
	}

	startup_msg->dsm_Result = -1;
	switch_sig_bit = AllocSignal(-1);

	if (switch_sig_bit != -1 && (ahi_port = CreateMsgPort()))
	{
		if ((ahi_request = (struct AHIRequest *) CreateIORequest(ahi_port, sizeof (struct AHIRequest))))
		{
			ahi_request->ahir_Version = 4;
			if ((ahi_device = OpenDevice(AHINAME, AHI_NO_UNIT, (struct IORequest *) ahi_request, 0)) == 0)
			{
				AHIBase = (struct Library*) ahi_request->ahir_Std.io_Device;

				/*dprintf("AllocAudio with %d channels, %d sounds and frequency %d\n", h->wh_Channels, AHI_BUFFERS, h->wh_Frequency);*/
				ahi_control = AHI_AllocAudio(AHIA_AudioID,   AHI_DEFAULT_ID,
													  AHIA_Channels,  h->wh_Channels,
													  AHIA_Sounds,	   AHI_BUFFERS,
													  AHIA_MixFreq,   h->wh_Frequency,
													  AHIA_SoundFunc, (ULONG) &OpenAL_SoundHook,
													  AHIA_UserData,	(ULONG) h,
													  TAG_DONE
													 );
				if (ahi_control)
				{
					ULONG buf_size;
					ULONG samples, fs, fm;

					AHI_GetAudioAttrs(AHI_INVALID_ID, ahi_control, AHIDB_MaxPlaySamples, (ULONG) &samples, TAG_DONE);
					AHI_ControlAudio(ahi_control, AHIC_MixFreq_Query, (ULONG) &fm, TAG_DONE);
					fs = h->wh_Frequency;

					buf_size = samples*fs/fm;
					/*dprintf("OpenAL: Minimum buffer size is %d, requested buffer size is %d\n", buf_size, h->wh_BufSize);*/
					if (buf_size > h->wh_BufSize)
						h->wh_BufSize = buf_size;

					sample_bufs = AllocVec(h->wh_BufSize*AHI_BUFFERS, MEMF_PUBLIC | MEMF_CLEAR);
					if (sample_bufs)
					{
						struct Buffer* bn;
						ULONG	buf;
						LONG err = AHIE_OK;

						sample_size = AHI_SampleFrameSize(h->wh_SampleType);

						for (buf = 0; buf < AHI_BUFFERS && err == AHIE_OK; buf++)
						{
							bn = &h->wh_Buffers[buf];
							bn->bn_SampleNo = buf;
							bn->bn_SampleInfo.ahisi_Type = h->wh_SampleType;
							bn->bn_SampleInfo.ahisi_Address = &sample_bufs[buf*h->wh_BufSize];
							bn->bn_SampleInfo.ahisi_Length = h->wh_BufSize/sample_size;
							InitSemaphore(&bn->bn_Semaphore);
							bn->bn_FillSize = 0;
							err = AHI_LoadSound(buf, AHIST_DYNAMICSAMPLE, &bn->bn_SampleInfo, ahi_control);
						}

						if (err != AHIE_OK)
						{
							FreeVec(sample_bufs);
							sample_bufs = NULL;
						}
					}
				}
			}
		}
	}

	if (sample_bufs)
	{
		BOOL dispatcher_running = TRUE;
		ULONG signal_mask = 1 << task_port->mp_SigBit;
		ULONG signal_set;
		struct MsgPort *reply_port;

		reply_port = CreateMsgPort();
		if (reply_port == NULL)
			reply_port = task_port;

		if (startup_msg)
			startup_msg->dsm_Result = 0;
		init_report->dir_Msg.mn_Node.ln_Type = NT_MESSAGE;
		init_report->dir_Msg.mn_ReplyPort = reply_port;
		init_report->dir_Msg.mn_Length = sizeof (struct DispatcherInitReport);
		AHI_ControlAudio(ahi_control, AHIC_MixFreq_Query, (ULONG) &init_report->dir_RealFrequency, TAG_DONE);
		init_report->dir_RealBufSize = h->wh_BufSize;
		PutMsg(startup_msg->dsm_Msg.mn_ReplyPort, (struct Message*) init_report);
		WaitPort(reply_port);
		GetMsg(reply_port);
		FreeVec(init_report);
		init_report = NULL;

		if (reply_port != task_port)
			DeleteMsgPort(reply_port);

		h->wh_SwitchSignal = 1UL << switch_sig_bit;
		h->wh_ReadBuf = 0;
		while (dispatcher_running)
		{
			signal_set = Wait(signal_mask);

			if (signal_set & (1 << task_port->mp_SigBit))
			{
				struct DispatcherMsg *msg;

				while ((msg = (struct DispatcherMsg *) GetMsg(task_port)))
				{
					if (msg->dm_Msg.mn_Length == sizeof (struct DispatcherMsg))
					{
						switch (msg->dm_Command)
						{
							case DISPATCHER_CMD_START:
							{
								/*
								 * First buffer has been filled and we were previously not
								 * playing any sound yet
								 */
								ULONG chan;
								ULONG cur_buf;

								cur_buf = h->wh_ReadBuf;
								AHI_ControlAudio(ahi_control, AHIC_Play, TRUE, TAG_DONE);

								/* Lock first audio buffer */
								ObtainSemaphore(&h->wh_Buffers[cur_buf].bn_Semaphore);
								locked_buf = cur_buf;

								for (chan = 0; chan < h->wh_Channels; chan++)
								{
									AHI_SetFreq(chan, h->wh_Frequency, ahi_control, AHISF_IMM);
									AHI_SetVol(chan, 0x10000L, -0x8000L, ahi_control, AHISF_IMM);
									AHI_SetSound(chan, cur_buf, 0, 0, ahi_control, AHISF_IMM);
								}

								Wait(1 << switch_sig_bit);
								cur_buf++;
								if (cur_buf >= AHI_BUFFERS)
									cur_buf = 0;
								h->wh_ReadBuf = cur_buf;

								signal_mask |= 1UL << switch_sig_bit;
								break;
							}

							case DISPATCHER_CMD_PAUSE:
							case DISPATCHER_CMD_RESUME:
								AHI_ControlAudio(ahi_control, AHIC_Play, msg->dm_Command == DISPATCHER_CMD_RESUME, TAG_DONE);
								break;

							case DISPATCHER_CMD_BREAK:
								/* Break requests and quit */
								/*dprintf("Dispatcher thread: break requested\n");*/
								AHI_ControlAudio(ahi_control, AHIC_Play, FALSE, TAG_DONE);
								dispatcher_running = FALSE;
								break;
						}
					}

					ReplyMsg((struct Message *) msg);
				}
			}

			if (signal_set & (1UL << switch_sig_bit))
			{
				/* Switch to next read buffer */
				ULONG cur_buf;

				cur_buf = h->wh_ReadBuf;
				/*dprintf("Dispatcher thread: buffer switch requested. Releasing lock on %d, locking %d\n", locked_buf, cur_buf);*/
				memset(h->wh_Buffers[locked_buf].bn_SampleInfo.ahisi_Address, 0, h->wh_BufSize);
				ReleaseSemaphore(&h->wh_Buffers[locked_buf].bn_Semaphore);
				cur_buf++;
				if (cur_buf >= AHI_BUFFERS)
					cur_buf = 0;
				ObtainSemaphore(&h->wh_Buffers[cur_buf].bn_Semaphore);
				locked_buf = cur_buf;
				h->wh_ReadBuf = cur_buf;
				/*dprintf("Dispatcher thread: buffer switch done\n");*/
			}
		}
	}

	/* Cleanup */
	if (init_report)
	{
		FreeVec(init_report);
		init_report = NULL;
	}

	if (locked_buf != -1)
	{
		ReleaseSemaphore(&h->wh_Buffers[locked_buf].bn_Semaphore);
		locked_buf = -1;
	}

	if (switch_sig_bit != -1)
	{
		FreeSignal(switch_sig_bit);
		switch_sig_bit = -1;
	}

	if (ahi_control)
	{
		AHI_FreeAudio(ahi_control);  /* Also unloads all sounds */
		ahi_control = NULL;
	}

	if (ahi_request)
	{
		CloseDevice((struct IORequest*) ahi_request);
		DeleteIORequest((struct IORequest*) ahi_request);
		ahi_request = NULL;
		ahi_device = -1;
	}

	if (sample_bufs)
	{
		FreeVec(sample_bufs);
		sample_bufs = NULL;
	}

	if (ahi_port)
	{
		DeleteMsgPort(ahi_port);
		ahi_port = NULL;
	}
}
Exemple #3
0
BOOL PlaySound( struct AHIUnitPrefs* prefs )
{
  struct AHIAudioCtrl* actrl;
  BOOL                 rc = FALSE;
  
  actrl = AHI_AllocAudio( AHIA_AudioID,  prefs->ahiup_AudioMode,
                          AHIA_MixFreq,  prefs->ahiup_Frequency,
                          AHIA_Channels, max( prefs->ahiup_Channels, 1 ),
                          AHIA_Sounds,   1,
                          TAG_DONE );

  if( actrl != NULL )
  {
    BYTE*                sample;
    int                  length = 48000/440;
    struct AHISampleInfo sound;
      
    sample = AllocVec( length, MEMF_PUBLIC );
      
    if( sample != NULL )
    {
      int i;
        
      for( i = 0; i < length; ++i )
      {
        sample[ i ] = 127 * sin( i * 2 * M_PI / length );
      }
        
      sound.ahisi_Type    = AHIST_M8S;
      sound.ahisi_Address = sample;
      sound.ahisi_Length  = length;
        
      if( AHI_LoadSound( 0, AHIST_SAMPLE, &sound, actrl ) == AHIE_OK )
      {
        if( AHI_ControlAudio( actrl, AHIC_Play,          TRUE,
                                     AHIC_MonitorVolume, prefs->ahiup_MonitorVolume,
                                     AHIC_InputGain,     prefs->ahiup_InputGain,
                                     AHIC_OutputVolume,  prefs->ahiup_OutputVolume,
                                     AHIC_Input,         prefs->ahiup_Input,
                                     AHIC_Output,        prefs->ahiup_Output,
                                     TAG_DONE ) == AHIE_OK )
        {
          AHI_Play( actrl, AHIP_BeginChannel, 0,
                           AHIP_Freq,         48000,
                           AHIP_Vol,          0x10000,
                           AHIP_Pan,          0x8000,
                           AHIP_Sound,        0,
                           AHIP_EndChannel,   NULL,
                           TAG_DONE );

          Delay( 50 );
          
          AHI_Play( actrl, AHIP_BeginChannel, 0,
                           AHIP_Sound,        AHI_NOSOUND,
                           AHIP_EndChannel,   NULL,
                           TAG_DONE );

          // Give the anti-click code a break ...
          Delay( 1 );

          AHI_ControlAudio( actrl, AHIC_Play, FALSE,
                                   TAG_DONE );
        }

        AHI_UnloadSound( 0, actrl );
      }
        
      FreeVec( sample );
    }
    
    AHI_FreeAudio( actrl );
  }

  return rc;
}
int
PlaySineEverywhere( void ) {
  int   rc = RETURN_OK;
  int   sine_length = 44100 / 100;
  BYTE* sine_m8s;
  BYTE* sine_s8s;
  WORD* sine_s16s;
  WORD* sine_m16s;
  LONG* sine_s32s;
  LONG* sine_m32s;

  sine_m8s  = AllocVec( 1 * sizeof( BYTE ) * sine_length, MEMF_ANY | MEMF_PUBLIC );
  sine_s8s  = AllocVec( 2 * sizeof( BYTE ) * sine_length, MEMF_ANY | MEMF_PUBLIC );
  sine_m16s = AllocVec( 1 * sizeof( WORD ) * sine_length, MEMF_ANY | MEMF_PUBLIC );
  sine_s16s = AllocVec( 2 * sizeof( WORD ) * sine_length, MEMF_ANY | MEMF_PUBLIC );
  sine_m32s = AllocVec( 1 * sizeof( LONG ) * sine_length, MEMF_ANY | MEMF_PUBLIC );
  sine_s32s = AllocVec( 2 * sizeof( LONG ) * sine_length, MEMF_ANY | MEMF_PUBLIC );
  
  if( sine_m8s != NULL &&
      sine_s8s != NULL &&
      sine_m16s != NULL &&
      sine_s16s != NULL &&
      sine_m32s != NULL &&
      sine_s32s != NULL ) {
    ULONG mode = AHI_INVALID_ID;
    int   i;

    for( i = 0; i < sine_length; ++i ) {
      double value = sin( i * 2 * M_PI / sine_length );

      sine_m8s[ i ] = (BYTE) ( SCHAR_MAX * value );
      sine_m16s[ i ] = (WORD) ( SHRT_MAX * value );
      sine_m32s[ i ] = (LONG) ( LONG_MAX * value );

      sine_s8s[ i * 2 + 0 ] = (BYTE) ( SCHAR_MAX * value );
      sine_s8s[ i * 2 + 1 ] = (BYTE) ( SCHAR_MAX * value );
      sine_s16s[ i * 2 + 0 ] = (WORD) ( SHRT_MAX * value );
      sine_s16s[ i * 2 + 1 ] = (WORD) ( SHRT_MAX * value );
      sine_s32s[ i * 2 + 0 ] = (LONG) ( LONG_MAX * value );
      sine_s32s[ i * 2 + 1 ] = (LONG) ( LONG_MAX * value );
    }

    while( rc == RETURN_OK &&
	   ( mode = AHI_NextAudioID( mode ) ) != AHI_INVALID_ID ) {
      struct AHIAudioCtrl* actrl;
      char                 name[ 64 ];
      struct Hook          sound_hook = {
	{ NULL, NULL },
	HookEntry,
	(HOOKFUNC) SoundFunc,
	FindTask( NULL )
      };
    
      AHI_GetAudioAttrs( mode, NULL,
			 AHIDB_Name, (ULONG) &name,
			 AHIDB_BufferLen, 64,
			 TAG_DONE );
    
      printf( "Mode 0x%08lx: %s\n", mode, name );

      actrl = AHI_AllocAudio( AHIA_AudioID,   mode,
			      AHIA_MixFreq,   44100,
			      AHIA_Channels,  1,
			      AHIA_Sounds,    6,
			      AHIA_SoundFunc, (ULONG) &sound_hook,
			      AHIA_UserData,  0,
			      TAG_DONE );

      if( actrl != NULL ) {
	struct AHISampleInfo sample_m8s  = { AHIST_M8S,  sine_m8s,  sine_length };
	struct AHISampleInfo sample_s8s  = { AHIST_S8S,  sine_s8s,  sine_length };
	struct AHISampleInfo sample_m16s = { AHIST_M16S, sine_m16s, sine_length };
	struct AHISampleInfo sample_s16s = { AHIST_S16S, sine_s16s, sine_length };
	struct AHISampleInfo sample_m32s = { AHIST_M32S, sine_m32s, sine_length };
	struct AHISampleInfo sample_s32s = { AHIST_S32S, sine_s32s, sine_length };
	
	if( AHI_LoadSound( 0, AHIST_SAMPLE, &sample_m8s,  actrl) == AHIE_OK &&
	    AHI_LoadSound( 1, AHIST_SAMPLE, &sample_s8s,  actrl) == AHIE_OK &&
	    AHI_LoadSound( 2, AHIST_SAMPLE, &sample_m16s, actrl) == AHIE_OK &&
	    AHI_LoadSound( 3, AHIST_SAMPLE, &sample_s16s, actrl) == AHIE_OK &&
	    AHI_LoadSound( 4, AHIST_SAMPLE, &sample_m32s, actrl) == AHIE_OK &&
	    AHI_LoadSound( 5, AHIST_SAMPLE, &sample_s32s, actrl) == AHIE_OK ) {

	  AHI_Play( actrl,
		    AHIP_BeginChannel, 0,
		    AHIP_Sound,        0,
		    AHIP_Freq,         44100,
		    AHIP_Vol,          0x10000,
		    AHIP_Pan,          0x00000,
		    AHIP_EndChannel,   0,
		    TAG_DONE );

	  // Now, when everything is "armed", lets start processing.

	  SetSignal( 0, SIGF_SINGLE );

	  if( AHI_ControlAudio( actrl,
				AHIC_Play, TRUE,
				TAG_DONE ) == AHIE_OK ) {
	    Wait( SIGF_SINGLE );

	    AHI_ControlAudio( actrl,
			      AHIC_Play, FALSE,
			      TAG_DONE );
	  }
	  else {
	    fprintf( stderr, "Unable start playback.\n" );
	    rc = RETURN_ERROR;
	  }

	  // AHI_FreeAudio() will unload the sounds
	}
	else {
	  fprintf( stderr, "Unable load sound.\n" );
	  rc = RETURN_ERROR;
	}
	
	AHI_FreeAudio( actrl );
      }
      else {
	fprintf( stderr, "Unable to allocate audio.\n" );
	rc = RETURN_ERROR;
      }
    }
  }
  else {
    fprintf( stderr, "Unable to allocate memory for sine\n" );
  }

  FreeVec( sine_m8s );
  FreeVec( sine_s8s );
  FreeVec( sine_s16s );
  FreeVec( sine_m16s );
  FreeVec( sine_s32s );
  FreeVec( sine_m32s );

  return rc;
}