void
SoundFunc( struct Hook*            hook,
	   struct AHIAudioCtrl*    actrl,
	   struct AHISoundMessage* sm ) {
  struct Task* task = hook->h_Data;
  ULONG        cnt;

  ++( (ULONG) actrl->ahiac_UserData );
  cnt = (ULONG) actrl->ahiac_UserData;
  
  if( cnt == 100 ) {
    AHI_SetSound( 0, AHI_NOSOUND, 0, 0, actrl, AHISF_NONE );
  }
  else if( cnt == 101 ) {
    Signal( task, SIGF_SINGLE );
  }
  else {
    UWORD sound = cnt % 6;

    AHI_SetSound( 0, sound, 0, 0, actrl, AHISF_NONE );

    if( ( sound == 0 ) ) {
      AHI_SetVol( 0, 0x10000, 0x10000 * cnt / 6 / ( 100 / 6 ), actrl, AHISF_NONE );
    }
  }
}
예제 #2
0
static ULONG OpenAL_SoundFunc(VOID)
{
	struct AHIAudioCtrl* ctrl = (struct AHIAudioCtrl*) REG_A2;
	struct AHISoundMessage* sm = (struct AHISoundMessage*) REG_A1;
	struct MOSWriteHandle* h = Handle(ctrl->ahiac_UserData);
	struct ExecBase *SysBase = *(struct ExecBase **) 4;

	AHI_SetSound(sm->ahism_Channel, h->wh_ReadBuf, 0, 0, ctrl, 0);

	/* When last channel has been started, request switching to next buffer */
	if (sm->ahism_Channel == h->wh_Channels-1)
		Signal((struct Task*) h->wh_DispatcherThread, h->wh_SwitchSignal);

	return 0;
}
예제 #3
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;
	}
}
예제 #4
0
ULONG
DevAbortIO( struct AHIRequest* ioreq,
            struct AHIBase*    AHIBase )
{
  ULONG rc = NULL;
  struct AHIDevUnit *iounit;
  
  if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
  {
    KPrintF("AbortIO(0x%08lx)", ioreq);
  }

  iounit = (struct AHIDevUnit *) ioreq->ahir_Std.io_Unit;
  
  ObtainSemaphore(&iounit->ListLock);
  if(ioreq->ahir_Std.io_Message.mn_Node.ln_Type != NT_REPLYMSG)
  {
    switch(ioreq->ahir_Std.io_Command)
    {

      case CMD_READ:
        if(FindNode((struct List *) &iounit->ReadList, (struct Node *) ioreq))
        {
          Remove((struct Node *) ioreq);
          ioreq->ahir_Std.io_Error = IOERR_ABORTED;
          TermIO(ioreq,AHIBase);
        }
        break;

      case CMD_WRITE:
      case AHICMD_WRITTEN:
        if(FindNode((struct List *) &iounit->PlayingList, (struct Node *) ioreq)
        || FindNode((struct List *) &iounit->SilentList, (struct Node *) ioreq)
        || FindNode((struct List *) &iounit->WaitingList, (struct Node *) ioreq))
        {
          struct AHIRequest *nextreq;

          while(ioreq)
          {
            Remove((struct Node *) ioreq);

            if(ioreq->ahir_Extras && (GetExtras(ioreq)->Channel != NOCHANNEL))
            {
              iounit->Voices[GetExtras(ioreq)->Channel].PlayingRequest = NULL;
              iounit->Voices[GetExtras(ioreq)->Channel].QueuedRequest = NULL;
              iounit->Voices[GetExtras(ioreq)->Channel].NextRequest = NULL;
              iounit->Voices[GetExtras(ioreq)->Channel].NextOffset = MUTE;
              if(iounit->AudioCtrl)
              {
                AHI_SetSound(GetExtras(ioreq)->Channel,AHI_NOSOUND,0,0,
                    iounit->AudioCtrl,AHISF_IMM);
              }
            }

            ioreq->ahir_Std.io_Command = CMD_WRITE;
            ioreq->ahir_Std.io_Error   = IOERR_ABORTED;
            nextreq = ioreq->ahir_Link;
            TermIO(ioreq,AHIBase);
            ioreq = nextreq;
          }
        }

      default:
        rc = IOERR_NOCMD;
        break;
    }
  }
  ReleaseSemaphore(&iounit->ListLock);

  if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_LOW)
  {
    KPrintF("=>%ld\n",rc);
  }

  return rc;
}