English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Language

 
 
Thread Tools
Old 31 March 2024, 19:20   #1
BSzili
old chunk of coal
 
BSzili's Avatar
 
Join Date: Nov 2011
Location: Hungary
Posts: 1,289
Noise after playing a sound with audio.device

I'd like to start non-looping sounds asynchronously both on a left and right channel using audio.device. I dusted off some old code I used in other projects, but there's a problem with clicks and pops after some sound effects.
It works by creating separate audio requests for the left and right channel, and uses the original request for control commands only. I apologize if this isn't the right forum section, but since the example code is in C I thought it should fit here.

Code:
#include <graphics/gfxbase.h>
#include <devices/audio.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/graphics.h>
#include <clib/alib_protos.h>

enum
{
	CHANNEL_LEFT,
	CHANNEL_RIGHT,
	CHANNEL_COUNT
};
#define LEFT_MASK 0x9
#define RIGHT_MASK 0x6

typedef struct
{
	struct MsgPort *port;
	struct IOAudio *ioreq;
	BYTE device;
} audiodev_t;

static BOOL audiodev_init(audiodev_t *dev, UBYTE *whichannel, ULONG chancount)
{
	if ((dev->port = CreateMsgPort()))
	{
		if ((dev->ioreq = (struct IOAudio *)CreateIORequest(dev->port, sizeof(struct IOAudio))))
		{
			struct IOAudio *audioReq = dev->ioreq;
			audioReq->ioa_Request.io_Message.mn_Node.ln_Pri = 127; // no stealing
			audioReq->ioa_Request.io_Command = ADCMD_ALLOCATE;
			audioReq->ioa_Request.io_Flags = ADIOF_NOWAIT;
			audioReq->ioa_AllocKey = 0;
			audioReq->ioa_Data = whichannel;
			audioReq->ioa_Length = chancount;
			if (!(dev->device = OpenDevice((STRPTR)AUDIONAME, 0, (struct IORequest *)audioReq, 0)))
			{
				return TRUE;
			}
		}
	}
	return FALSE;
}

static void audiodev_close(audiodev_t *dev)
{
	if (!dev->device)
	{
		struct IOAudio *audioReq = dev->ioreq;
		audioReq->ioa_Request.io_Command = CMD_RESET;
		audioReq->ioa_Request.io_Flags = 0;
		DoIO((struct IORequest *)audioReq);
		CloseDevice((struct IORequest *)audioReq);
		dev->device = -1;
	}

	if (dev->ioreq)
	{
		DeleteIORequest((struct IORequest *)dev->ioreq);
		dev->ioreq = NULL;
	}

	if (dev->port)
	{
		DeleteMsgPort(dev->port);
		dev->port = NULL;
	}
}

static audiodev_t digidev;
static struct IOAudio digiChannelReq[CHANNEL_COUNT];
static LONG audioClock;
static UWORD audioPeriod;

static void channel_init(struct IOAudio *srcio, struct IOAudio *destio, ULONG chanmask)
{
	CopyMem(srcio, destio, sizeof(struct IOAudio));
	destio->ioa_Request.io_Unit = (struct Unit *)((ULONG)destio->ioa_Request.io_Unit & chanmask);
	destio->ioa_Request.io_Message.mn_ReplyPort = CreateMsgPort();
	destio->ioa_Request.io_Message.mn_Node.ln_Type = 0;
	destio->ioa_Length = 0;
	destio->ioa_Request.io_Command = CMD_WRITE;
}

static void channel_close(struct IOAudio *destio)
{
	destio->ioa_Request.io_Command = CMD_FLUSH;
	destio->ioa_Request.io_Flags = 0;
	DoIO((struct IORequest *)destio);
	if (destio->ioa_Request.io_Message.mn_ReplyPort)
	{
		DeleteMsgPort(destio->ioa_Request.io_Message.mn_ReplyPort);
		destio->ioa_Request.io_Message.mn_ReplyPort = NULL;
	}
}

int sound_init(int rate)
{
	UBYTE whichannel[] = {3, 5, 10, 12};

	if (audiodev_init(&digidev, whichannel, sizeof(whichannel)))
	{
		channel_init(digidev.ioreq, &digiChannelReq[CHANNEL_LEFT], LEFT_MASK);
		channel_init(digidev.ioreq, &digiChannelReq[CHANNEL_RIGHT], RIGHT_MASK);

		if (GfxBase->DisplayFlags & PAL)
			audioClock = 3546895;
		else
			audioClock = 3579545;

		audioPeriod = audioClock / rate;

		return 1;
	}
	audiodev_close(&digidev);

	return 0;
}

void sound_close(void)
{
	channel_close(&digiChannelReq[CHANNEL_LEFT]);
	channel_close(&digiChannelReq[CHANNEL_RIGHT]);
	audiodev_close(&digidev);
}

static void channel_setup(struct IOAudio *audioio, UBYTE *data, ULONG length, UWORD period, UWORD volume, UWORD cycles)
{
	audioio->ioa_Data = data;
	audioio->ioa_Length = length;
	audioio->ioa_Period = period;
	audioio->ioa_Volume = volume;
	audioio->ioa_Cycles = cycles;
	audioio->ioa_Request.io_Flags = ADIOF_PERVOL;
}

void sound_stop(void)
{
	struct IOAudio *audioReq = digidev.ioreq;
	audioReq->ioa_Request.io_Command = CMD_FLUSH;
	DoIO((struct IORequest *)audioReq);
}

void sound_play(char *data, int length, int rate, int leftvol, int rightvol, int cycles)
{
	struct IOAudio *audioReq = digidev.ioreq;
	struct IOAudio *digiLeftReq = &digiChannelReq[CHANNEL_LEFT];
	struct IOAudio *digiRightReq = &digiChannelReq[CHANNEL_RIGHT];
	GetMsg(digiLeftReq->ioa_Request.io_Message.mn_ReplyPort);
	GetMsg(digiRightReq->ioa_Request.io_Message.mn_ReplyPort);
	audioReq->ioa_Request.io_Command = CMD_STOP;
	DoIO((struct IORequest *)audioReq);
	channel_setup(digiLeftReq, data, length, audioPeriod, leftvol, cycles);
	channel_setup(digiRightReq, data, length, audioPeriod, rightvol, cycles);
	BeginIO((struct IORequest *)digiLeftReq);
	BeginIO((struct IORequest *)digiRightReq);
	audioReq->ioa_Request.io_Command = CMD_START;
	DoIO((struct IORequest *)audioReq);
}

#include "sound19.h"
int main(int argc, char *argv[])
{
	if (!sound_init(8000))
		return 1;

	Printf("Playing the sound...\n");
	sound_play(sound19_au, sound19_au_len, 0, 64, 64, 1);
	Printf("Waiting for 10 seconds...\n");
	Delay(10*50);

	sound_close();

	return 0;
}
I'm clearly missing something here, as there 's noise after certain effects. The amount varies by the setup, but it's always there even if it's only a couple pops

I'm attaching the the problematic sound, so the code can be built with gcc:
Code:
m68k-amigaos-gcc -o sndtest audiodev.c -noixemul
Attached Files
File Type: zip sound19.zip (4.1 KB, 53 views)
BSzili is offline  
Old 31 March 2024, 19:36   #2
a/b
Registered User
 
Join Date: Jun 2016
Location: europe
Posts: 1,039
This works fine for me as is, and also after changing it to loop with 1sec delay.
Are the lengths correct? I'd use this instead, e.g.
Code:
// unsigned int sound19_au_len = 3040;
unsigned int sound19_au_len = sizeof(sound19_au);
a/b is offline  
Old 31 March 2024, 19:59   #3
BSzili
old chunk of coal
 
BSzili's Avatar
 
Join Date: Nov 2011
Location: Hungary
Posts: 1,289
The length should be correct, but this is more than just a couple garbage samples. The clicks and pops can happen long after the sound stopped playing, which is why I added a longer delay. It's also not a 100% consistent, e.g. sometimes there are lots of clicks, sometimes only a pop a few seconds after the sound.
BSzili is offline  
Old 01 April 2024, 11:20   #4
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 1,975
I dont use audio.device especially, only for some players. I think You must add something like playing null/empty sample at end of your routine.
Anyway audio.device is buggy, missing DMAWait for fast CPU's.
I dont know if it was fixed for kickstart 3.2.
Then using audio.device is not very good choice for me.
But if You want to see how is coded the biggest Amiga replay which using audio.device, then You can see MaxTrax original replay source (available on Wanted Team page).
Don_Adan is offline  
Old 01 April 2024, 11:48   #5
Galahad/FLT
Going nowhere
 
Galahad/FLT's Avatar
 
Join Date: Oct 2001
Location: United Kingdom
Age: 50
Posts: 8,994
Make sure that first longword of all samples is null, that should remove clicks and pops
Galahad/FLT is offline  
Old 01 April 2024, 13:33   #6
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 1,975
Yes, but it will be fix/modify data, not program.
For me the best (universal) solution is next:
1. Alloc 2 bytes longer chip ram buffer, than is necessary for sample to playing.
2. Clear first 2 bytes of this buffer.
3. Load sample to play at buffer + 2 bytes.
4. Add 1 (for audio.device, this is perhaps 2, if I remember right) to played sample length.
Don_Adan is offline  
Old 01 April 2024, 22:03   #7
BSzili
old chunk of coal
 
BSzili's Avatar
 
Join Date: Nov 2011
Location: Hungary
Posts: 1,289
I'm trying to keep things system friendly, so I opted to use audio.device. I'm looking at the MaxTrax sources, but it seems to do some peeking and poking at the chipset registers too, I guess the audio.device limitations necessitated things like DMAWait.
Thanks for tips, I tried both 2 and 4 bytes of silence at the beginning of the sample, but the noise still persists after problematic one ends one cycle.
I guess an alternate solution would be to create a softint for the reply message that does a CMD_FLUSH or something similar.
BSzili is offline  
Old 02 April 2024, 00:23   #8
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 1,975
I dont remember, If MaxTrax used chipset registers too. Maybe it was added by me for Volume handling for EaglePlayer.

If You still hear strange noise, then for me can be one of two possibilities.
1. Repeat sample length is greatar than 1 (2 for audio device)
2. Audio.device dont loop to begining of sample, but is stoped/looped at end of sample.
If this is reason, then 2 empty bytes must be et end of sample, not at begining.

From my memory Action Replay 3 has command to show Amiga chip registers values.
Simple, play this sample. When strange noise occured, enter to AR3, show registers.
Find audio address registers and later check which value is played.
Don_Adan is offline  
Old 02 April 2024, 07:20   #9
BSzili
old chunk of coal
 
BSzili's Avatar
 
Join Date: Nov 2011
Location: Hungary
Posts: 1,289
I think padding the end of the sample with zeroes have fixed it! I'll give it some more testing on different setups to make sure.
BSzili is offline  
Old 02 April 2024, 21:58   #10
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 1,975
Nice.
Then for fixing source code.
1. Must be allocated 2 bytes greater buffer than loaded sample of cleared chip memory.
2. And 2 bytes greater length than loaded sample must be played.
Don_Adan is offline  
Old 03 April 2024, 10:17   #11
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 1,975
After rethinking some time, perhaps sample length (to play) must be done via similar code:

Code:
 move.l LoadedLength,D0
 addq.l #3,D0
 bclr #0,D0
Dependent how audio.device is handling odd length samples, via:

Code:
 bclr #0,D0
or

Code:
 addq.l #1,D0
 bclr #0,D0
Simple

Code:
 addq.l #2,D0
can be not enough to remove strange noises at end of sample playing.
Don_Adan is offline  
Old 03 April 2024, 20:29   #12
BSzili
old chunk of coal
 
BSzili's Avatar
 
Join Date: Nov 2011
Location: Hungary
Posts: 1,289
You mean rounding the length up to the next word/long boundary? I'm not sure if that'll do much in this case, as the problematic sample is 3040 bytes long.
BSzili is offline  
Old 04 April 2024, 01:07   #13
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 1,975
Yes.
Try to add f.e 1000 null bytes at end of problematic sample. Maybe this sample is loaded in any special chip ram location or wrong size to playing is set?
And of course some samples can be damaged too.
You can hear this sample under FileMaster 2.2.
Or use AR3 and check which word is playing, when problem occured.
Don_Adan is offline  
Old 04 April 2024, 11:29   #14
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 55
Posts: 1,975
From my memory strange noises can occured, if:
1. Wrong area is played, f.e fast ram.
2. Wrong period is set.
3. Not sample data in chip mem is played.
Don_Adan is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Crackling Noise starting Audio with theplayer routine Emufr3ak Coders. Asm / Hardware 10 25 February 2024 17:52
Stereo sound with audio.device BSzili Coders. System 2 22 February 2022 21:37
Video and Audio Noise in Amiga 600 Rev 1.5 Nibbler support.Hardware 10 09 March 2020 13:01
Amiga 2000 that previously had sound not playing sound after repairs DCF support.Hardware 1 18 September 2019 06:41
A1200 - Audio noise NovaCoder support.Hardware 6 11 March 2012 23:57

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 21:58.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.08347 seconds with 16 queries