mirror of
https://github.com/Zeal-Operating-System/ZealOS.git
synced 2024-12-25 23:10:32 +00:00
Add temporary Sound dir and modified driver files.
Sources: AC97: https://git.checksum.fail/alec/TOSamp HDAudio0: https://git.checksum.fail/alec/templenes HDAudio1: https://github.com/dancoyle21/sup1hdaudio (fork of alec's sup1hdaudio repo)
This commit is contained in:
parent
b14b485716
commit
b7821cbc95
21 changed files with 4530 additions and 0 deletions
244
src/Home/Sound/AC97/AC97.ZC
Normal file
244
src/Home/Sound/AC97/AC97.ZC
Normal file
|
@ -0,0 +1,244 @@
|
||||||
|
|
||||||
|
#define INT_LAST_VALID_ENTRY 1 << 2
|
||||||
|
#define INT_IOC 1 << 3
|
||||||
|
#define INT_FIFO_ERR 1 << 4
|
||||||
|
#define BDL_BUF_SIZE 2044
|
||||||
|
#define PCM_BUF_SIZE 2048
|
||||||
|
#define MAX_BDLS 32
|
||||||
|
#define PCM_IN 0
|
||||||
|
#define PCM_OUT 1
|
||||||
|
#define MIC_IN 2
|
||||||
|
|
||||||
|
// Native Audio Mixer registers (all U16)
|
||||||
|
#define RESET 0x00 // Reset Register
|
||||||
|
#define MASTER_VOL 0x02 // Set Master Output Volume
|
||||||
|
#define MIC_VOL 0x0E // Set Microphone Volume
|
||||||
|
#define PCM_VOL 0x18 // Set Output Volume of PCM patterns
|
||||||
|
#define REC_SLC 0x1A // Select Input Device
|
||||||
|
#define REC_GAIN 0x1C // Set Input Gain
|
||||||
|
#define MIC_GAIN 0x1E // Set Gain of Microphone
|
||||||
|
#define EXT_ID 0x28 // Supported extended functions
|
||||||
|
#define EXT_CTRL 0x2A // Enabling extended functions
|
||||||
|
#define EXT_FRONT_RATE 0x2C // Sample rate of front speaker
|
||||||
|
|
||||||
|
// Native Audio Bus Master registers
|
||||||
|
#define PCM_INPUT_REG_BOX\
|
||||||
|
0x00 // NABM register box for PCM IN (sizeof NABM register box)
|
||||||
|
#define PCM_OUTPUT_REG_BOX\
|
||||||
|
0x10 // NABM register box for PCM OUT (sizeof NABM register box)
|
||||||
|
#define MIC_INPUT_REG_BOX\
|
||||||
|
0x20 // NABM register box for Microphone (sizeof NABM register box)
|
||||||
|
#define GLOBAL_CTL 0x2C // Global Control Register (U32)
|
||||||
|
#define GLOBAL_STS 0x30 // Global Status Register (U32)
|
||||||
|
|
||||||
|
// NABM register box registers
|
||||||
|
#define BUFFER_DSC_ADDR 0x00 // Physical Address of Buffer Descriptor List (U32)
|
||||||
|
#define CUR_ENTRY_VAL\
|
||||||
|
0x04 // Number of Actual Processed Buffer Descriptor Entry (U8)
|
||||||
|
#define LAST_VALID_ENTRY 0x05 // Number of all Descriptor Entries (U8)
|
||||||
|
#define TRANSFER_STS 0x06 // Status of Transferring Data (U16)
|
||||||
|
#define CUR_IDX_PROC_SAMPLES\
|
||||||
|
0x08 // Number of Transferred Samples in Actual Processed Entry (U16)
|
||||||
|
#define PRCSD_ENTRY 0x0A // Number of Actual Processed Buffer Entry (U8)
|
||||||
|
#define BUFFER_CNT\
|
||||||
|
0x0B // Most Important Register for controlling Transfers (U8)
|
||||||
|
|
||||||
|
class @ac97_bdl_entry
|
||||||
|
{
|
||||||
|
U32 addr;
|
||||||
|
U16 length; // length - 1
|
||||||
|
U16 flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
class @ac97_bdl
|
||||||
|
{
|
||||||
|
@ac97_bdl_entry entries[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
class @ac97
|
||||||
|
{
|
||||||
|
@pci_info pci;
|
||||||
|
@ac97_bdl *bdl[3];
|
||||||
|
U16 nam;
|
||||||
|
U16 nabm;
|
||||||
|
};
|
||||||
|
|
||||||
|
@ac97 AC97;
|
||||||
|
|
||||||
|
#define AUDIO_MAX_STREAMS 16
|
||||||
|
#define AUDIO_OUTPUT_BUFFER_SIZE 1024
|
||||||
|
#define AUDIO_STREAM_FIFO_SIZE 1048576 * 16
|
||||||
|
#define AUDIO_STREAM_TYPE_INPUT 0
|
||||||
|
#define AUDIO_STREAM_TYPE_OUTPUT 1
|
||||||
|
|
||||||
|
class @audio_stream
|
||||||
|
{
|
||||||
|
CFifoI64 * data;
|
||||||
|
};
|
||||||
|
|
||||||
|
class @audio
|
||||||
|
{
|
||||||
|
@audio_stream output[AUDIO_MAX_STREAMS];
|
||||||
|
I64 output_frames[AUDIO_MAX_STREAMS];
|
||||||
|
};
|
||||||
|
|
||||||
|
@audio Audio;
|
||||||
|
|
||||||
|
U0 @audio_init()
|
||||||
|
{
|
||||||
|
I64 i = 0;
|
||||||
|
for (i = 0; i < AUDIO_MAX_STREAMS; i++)
|
||||||
|
Audio.output[i].data = FifoI64New(AUDIO_STREAM_FIFO_SIZE, sys_task);
|
||||||
|
}
|
||||||
|
|
||||||
|
@audio_init;
|
||||||
|
|
||||||
|
I64 @audio_get_available_output_stream()
|
||||||
|
{
|
||||||
|
I64 stream = 0;
|
||||||
|
while (FifoI64Count(Audio.output[stream].data))
|
||||||
|
stream++;
|
||||||
|
if (stream > AUDIO_MAX_STREAMS - 1)
|
||||||
|
return -1;
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
I64 @audio_play_sfx(U32 *data, I64 length)
|
||||||
|
{
|
||||||
|
I64 i;
|
||||||
|
I64 stream = @audio_get_available_output_stream;
|
||||||
|
if (stream < 0)
|
||||||
|
return stream;
|
||||||
|
for (i = 0; i < length; i++)
|
||||||
|
FifoI64Ins(Audio.output[stream].data, data[i]);
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 @ac97_mix_output(U32 *buf, I64 length = NULL)
|
||||||
|
{
|
||||||
|
I64 i;
|
||||||
|
I64 j;
|
||||||
|
I64 acc_sample_L = 0;
|
||||||
|
I64 acc_sample_R = 0;
|
||||||
|
I64 acc_streams = 0;
|
||||||
|
U32 sample;
|
||||||
|
|
||||||
|
if (!length)
|
||||||
|
length = AUDIO_OUTPUT_BUFFER_SIZE;
|
||||||
|
for (i = 0; i < length / 4; i++)
|
||||||
|
{
|
||||||
|
acc_sample_L = 0;
|
||||||
|
acc_sample_R = 0;
|
||||||
|
acc_streams = 0;
|
||||||
|
|
||||||
|
for (j = 0; j < AUDIO_MAX_STREAMS; j++)
|
||||||
|
{
|
||||||
|
if (FifoI64Count(Audio.output[j].data))
|
||||||
|
{
|
||||||
|
FifoI64Remove(Audio.output[j].data, &sample);
|
||||||
|
Audio.output_frames[j]++;
|
||||||
|
acc_streams++;
|
||||||
|
acc_sample_L += sample.u16[0];
|
||||||
|
acc_sample_R += sample.u16[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[i].i16[0] = ToI64(acc_sample_L / Sqrt(acc_streams));
|
||||||
|
buf[i].i16[1] = ToI64(acc_sample_R / Sqrt(acc_streams));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 @ac97_fill_buffer()
|
||||||
|
{
|
||||||
|
I64 idx = InU8(AC97.nabm + PCM_OUTPUT_REG_BOX + LAST_VALID_ENTRY);
|
||||||
|
U32 *buf = AC97.bdl[PCM_OUT]->entries[idx].addr;
|
||||||
|
@ac97_mix_output(buf, BDL_BUF_SIZE);
|
||||||
|
OutU8(AC97.nabm + PCM_OUTPUT_REG_BOX + LAST_VALID_ENTRY, ++idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 @ac97_process_audio()
|
||||||
|
{
|
||||||
|
U16 status = InU16(AC97.nabm + PCM_OUTPUT_REG_BOX + TRANSFER_STS);
|
||||||
|
if (status & INT_IOC)
|
||||||
|
{
|
||||||
|
@ac97_fill_buffer;
|
||||||
|
OutU16(AC97.nabm + PCM_OUTPUT_REG_BOX + TRANSFER_STS, 0x1C);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
I64 @ac97_init()
|
||||||
|
{
|
||||||
|
I64 i;
|
||||||
|
I64 j;
|
||||||
|
// Scan for device
|
||||||
|
j = PCIClassFind(0x040100, 0);
|
||||||
|
if (j < 0)
|
||||||
|
{
|
||||||
|
device_not_found: SysLog("\n[AC'97] Device not found\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@get_pci_info(j, &AC97.pci);
|
||||||
|
|
||||||
|
if (AC97.pci.vendor_id != 0x8086 || AC97.pci.device_id != 0x2415)
|
||||||
|
goto device_not_found;
|
||||||
|
|
||||||
|
AC97.nam = AC97.pci.bar[0] &0xFFFFFF00;
|
||||||
|
AC97.nabm = AC97.pci.bar[1] &0xFFFFFF00;
|
||||||
|
|
||||||
|
// Enable port IO, disable MMIO
|
||||||
|
PCIWriteU8(j.u8[2], j.u8[1], j.u8[0], 0x4, 5);
|
||||||
|
|
||||||
|
OutU32(AC97.nabm + GLOBAL_CTL, 0x03);
|
||||||
|
OutU16(AC97.nam + RESET, 0xFFFF);
|
||||||
|
|
||||||
|
// Set PCM Output to Max volume
|
||||||
|
OutU16(AC97.nam + PCM_VOL, 0x0000);
|
||||||
|
|
||||||
|
// Allocate Buffer Descriptor Lists
|
||||||
|
AC97.bdl[PCM_IN] = CAllocAligned(sizeof(@ac97_bdl), 4096, Fs->code_heap);
|
||||||
|
AC97.bdl[PCM_OUT] = CAllocAligned(sizeof(@ac97_bdl), 4096, Fs->code_heap);
|
||||||
|
AC97.bdl[MIC_IN] = CAllocAligned(sizeof(@ac97_bdl), 4096, Fs->code_heap);
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_BDLS; i++)
|
||||||
|
{
|
||||||
|
AC97.bdl[PCM_OUT]->entries[i].addr =
|
||||||
|
CAllocAligned(PCM_BUF_SIZE, 4096, Fs->code_heap);
|
||||||
|
AC97.bdl[PCM_OUT]->entries[i].length = BDL_BUF_SIZE / 2;
|
||||||
|
AC97.bdl[PCM_OUT]->entries[i].flags = 1 << 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set addresses of Buffer Descriptor Lists
|
||||||
|
// OutU32(AC97.nabm + PCM_INPUT_REG_BOX + BUFFER_DSC_ADDR, AC97.bdl[PCM_IN]);
|
||||||
|
OutU32(AC97.nabm + PCM_OUTPUT_REG_BOX + BUFFER_DSC_ADDR, AC97.bdl[PCM_OUT]);
|
||||||
|
// OutU32(AC97.nabm + MIC_INPUT_REG_BOX + BUFFER_DSC_ADDR, AC97.bdl[MIC_IN]);
|
||||||
|
|
||||||
|
// Set Master Volume
|
||||||
|
OutU16(AC97.nam + MASTER_VOL, 0x0F0F);
|
||||||
|
|
||||||
|
// Stop playing sound
|
||||||
|
OutU8(AC97.nabm + PCM_OUTPUT_REG_BOX + BUFFER_CNT, 0);
|
||||||
|
|
||||||
|
// Fill one buffers
|
||||||
|
@ac97_fill_buffer;
|
||||||
|
|
||||||
|
// Enable interrupt handler
|
||||||
|
//@pci_register_int_handler(&@ac97_int_handler);
|
||||||
|
|
||||||
|
// Start playing sound
|
||||||
|
OutU8(AC97.nabm + PCM_OUTPUT_REG_BOX + BUFFER_CNT, 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 @ac97_task()
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
@ac97_process_audio;
|
||||||
|
Sleep(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ac97_init;
|
||||||
|
Spawn(&@ac97_task,, "AC97 Task", 1);
|
89
src/Home/Sound/AC97/Pci.ZC
Normal file
89
src/Home/Sound/AC97/Pci.ZC
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
#define PCI_INTH_MAX 16
|
||||||
|
|
||||||
|
U64 @pci_int_handler[PCI_INTH_MAX];
|
||||||
|
|
||||||
|
class @pci_info {
|
||||||
|
U16 vendor_id;
|
||||||
|
U16 device_id;
|
||||||
|
U16 command;
|
||||||
|
U16 status;
|
||||||
|
U32 _class;
|
||||||
|
U32 bar[6];
|
||||||
|
U32 cap_pointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
class @pci_cap {
|
||||||
|
U8 cap_vndr; /* Generic PCI field: PCI_CAP_ID_VNDR */
|
||||||
|
U8 cap_next; /* Generic PCI field: next ptr. */
|
||||||
|
U8 cap_len; /* Generic PCI field: capability length */
|
||||||
|
U8 cfg_type; /* Identifies the structure. */
|
||||||
|
U8 bar; /* Where to find it. */
|
||||||
|
U8 padding[3]; /* Pad to full dword. */
|
||||||
|
U32 offset; /* Offset within bar. */
|
||||||
|
U32 length; /* Length of the structure, in bytes. */
|
||||||
|
};
|
||||||
|
|
||||||
|
U0 @get_pci_info(I64 i, @pci_info *pci) {
|
||||||
|
I64 j;
|
||||||
|
pci->vendor_id = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], 0x0) & 0xFFFF;
|
||||||
|
pci->device_id = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], 0x0) >> 16;
|
||||||
|
pci->command = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], 0x4) & 0xFFFF;
|
||||||
|
pci->status = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], 0x4) >> 16;
|
||||||
|
pci->_class = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], 0x8) >> 24;
|
||||||
|
for (j = 0; j < 6; j++)
|
||||||
|
pci->bar[j] = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], 0x10 + (0x04 * j));
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 @get_pci_cap(I64 i, @pci_cap *cap, I64 idx) {
|
||||||
|
I64 base = 0x40 + (idx * 16);
|
||||||
|
U32 u32;
|
||||||
|
u32 = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], base);
|
||||||
|
cap->cap_vndr = u32.u8[0];
|
||||||
|
cap->cap_next = u32.u8[1];
|
||||||
|
cap->cap_len = u32.u8[2];
|
||||||
|
cap->cfg_type = u32.u8[3];
|
||||||
|
u32 = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], base + 0x04);
|
||||||
|
cap->bar = u32.u8[0];
|
||||||
|
cap->offset = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], base + 0x08);
|
||||||
|
cap->length = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], base + 0x0c);
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 @pci_reroute_interrupts(I64 base, I64 cpu) {
|
||||||
|
I64 i;
|
||||||
|
U8 *da = dev.uncached_alias + IOAPIC_REG;
|
||||||
|
U32 *_d = dev.uncached_alias + IOAPIC_DATA;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
*da = IOREDTAB + i * 2 + 1;
|
||||||
|
*_d = dev.mp_apic_ids[cpu] << 24;
|
||||||
|
*da = IOREDTAB + i * 2;
|
||||||
|
*_d = 0x4000 + base + i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
I64 @pci_register_int_handler(U64 handler) {
|
||||||
|
if (!handler)
|
||||||
|
return -1;
|
||||||
|
I64 i = 0;
|
||||||
|
while (@pci_int_handler[i])
|
||||||
|
i++;
|
||||||
|
if (i > PCI_INTH_MAX - 1)
|
||||||
|
return -1;
|
||||||
|
@pci_int_handler[i] = handler;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
interrupt U0 @pci_interrupt_handler() {
|
||||||
|
I64 i;
|
||||||
|
for (i = 0; i < PCI_INTH_MAX; i++)
|
||||||
|
if (@pci_int_handler[i])
|
||||||
|
Call(@pci_int_handler[i]);
|
||||||
|
*(dev.uncached_alias + LAPIC_EOI)(U32 *) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemSet(&@pci_int_handler, NULL, sizeof(U64) * PCI_INTH_MAX);
|
||||||
|
// IntEntrySet(0x40, &@pci_interrupt_handler, IDTET_IRQ);
|
||||||
|
// IntEntrySet(0x41, &@pci_interrupt_handler, IDTET_IRQ);
|
||||||
|
// IntEntrySet(0x42, &@pci_interrupt_handler, IDTET_IRQ);
|
||||||
|
// IntEntrySet(0x43, &@pci_interrupt_handler, IDTET_IRQ);
|
||||||
|
//@pci_reroute_interrupts(0x40, 0);
|
76
src/Home/Sound/HDAudio0/Audio.ZC
Normal file
76
src/Home/Sound/HDAudio0/Audio.ZC
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
// vim: set ft=c:
|
||||||
|
|
||||||
|
I64 start_buf_num;
|
||||||
|
U0 (*fp_old_fill_buf)(SND_OUT_CONTAINER *buf,I64 buf_num)=NULL;
|
||||||
|
|
||||||
|
U0 AudioFillBuf(SND_OUT_CONTAINER *buf,I64 buf_num)
|
||||||
|
{
|
||||||
|
I64 j=0,k;
|
||||||
|
I64 intL, intR;
|
||||||
|
U8 *buf2;
|
||||||
|
|
||||||
|
if (paused)
|
||||||
|
{
|
||||||
|
while (j<SND_BUF_LEN)
|
||||||
|
{
|
||||||
|
buf[j++]=0;
|
||||||
|
buf[j++]=0;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (j<SND_BUF_LEN)
|
||||||
|
{
|
||||||
|
// TODO: fix this - dirty hack to keep audio in sync
|
||||||
|
if (FifoI64Cnt(audio_fifo_L)>8192)
|
||||||
|
{
|
||||||
|
while (FifoI64Cnt(audio_fifo_L)>7680)
|
||||||
|
{
|
||||||
|
FifoI64Rem(audio_fifo_L, &k);
|
||||||
|
FifoI64Rem(audio_fifo_R, &k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FifoI64Cnt(audio_fifo_L))
|
||||||
|
{
|
||||||
|
FifoI64Rem(audio_fifo_L, &intL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
intL = 0;
|
||||||
|
}
|
||||||
|
intL *= 0xFFFF;
|
||||||
|
if (intL < 0)
|
||||||
|
{
|
||||||
|
intL += 0x1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FifoI64Cnt(audio_fifo_R))
|
||||||
|
{
|
||||||
|
FifoI64Rem(audio_fifo_R, &intR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
intR = 0;
|
||||||
|
}
|
||||||
|
intR *= 0xFFFF;
|
||||||
|
if (intR < 0)
|
||||||
|
{
|
||||||
|
intR += 0x1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf2 = buf+j;
|
||||||
|
buf2[0] = 0;
|
||||||
|
buf2[1] = intL;
|
||||||
|
buf2[2] = intL >> 8;
|
||||||
|
buf2[3] = intL >> 16;
|
||||||
|
j++;
|
||||||
|
|
||||||
|
buf2 = buf+j;
|
||||||
|
buf2[0] = 0;
|
||||||
|
buf2[1] = intR;
|
||||||
|
buf2[2] = intR >> 8;
|
||||||
|
buf2[3] = intR >> 16;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
1052
src/Home/Sound/HDAudio0/HDAudio.ZC
Normal file
1052
src/Home/Sound/HDAudio0/HDAudio.ZC
Normal file
File diff suppressed because it is too large
Load diff
6
src/Home/Sound/HDAudio1/Load.ZC
Normal file
6
src/Home/Sound/HDAudio1/Load.ZC
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
Cd(__DIR__);
|
||||||
|
|
||||||
|
SysFile("Sup1CodeScraps/Mem/Mem2Meg.ZC");
|
||||||
|
SysFile("Sup1Snd/MakeSnd.ZC");
|
||||||
|
SysFile("Sup1HDAudio/HDAudio.ZC");
|
||||||
|
|
199
src/Home/Sound/HDAudio1/Sup1CodeScraps/Mem/Mem2Meg.ZC
Normal file
199
src/Home/Sound/HDAudio1/Sup1CodeScraps/Mem/Mem2Meg.ZC
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
//Now, we use 1 Gig page table entries.
|
||||||
|
|
||||||
|
//See $LK,"./UncachedAlloc.ZC"$
|
||||||
|
|
||||||
|
U8 *Mem2MegAlloc(I64 *_pages2Meg,CBlkPool *bp=NULL)
|
||||||
|
{/*Alloc 2Meg pages from BlkPool. Don't link to task.
|
||||||
|
(Linking to a task means they will be freed when the task dies.)
|
||||||
|
It might give you more than you asked for
|
||||||
|
so a ptr to a page count is passed.
|
||||||
|
|
||||||
|
Return: NULL if out of memory.
|
||||||
|
*/
|
||||||
|
I64 i,j,*pte,num=*_pages2Meg;
|
||||||
|
CMemBlk *res=NULL,*m,*m1;
|
||||||
|
|
||||||
|
if (!bp) bp=sys_code_bp;
|
||||||
|
PUSHFD
|
||||||
|
CLI
|
||||||
|
while (LBts(&bp->locked_flags,BPlf_LOCKED))
|
||||||
|
PAUSE
|
||||||
|
num<<=21-MEM_PAG_BITS;
|
||||||
|
|
||||||
|
m=&bp->mem_free_2meg_list;
|
||||||
|
while (TRUE) {
|
||||||
|
if (!(res=m->next))
|
||||||
|
break;
|
||||||
|
if (res->pags<num)
|
||||||
|
m=res;
|
||||||
|
else {
|
||||||
|
if (res->pags==num) {
|
||||||
|
m->next=res->next;
|
||||||
|
goto am_done;
|
||||||
|
} else {
|
||||||
|
res->pags-=num;
|
||||||
|
res(U8 *)+=res->pags<<MEM_PAG_BITS;
|
||||||
|
res->pags=num;
|
||||||
|
goto am_done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m=&bp->mem_free_list;
|
||||||
|
while (TRUE) {
|
||||||
|
if (!(res=m->next)) {
|
||||||
|
num=0;
|
||||||
|
res=NULL; //Out of memory
|
||||||
|
goto am_done;
|
||||||
|
}
|
||||||
|
if (res->pags<num)
|
||||||
|
m=res;
|
||||||
|
else {
|
||||||
|
if (res->pags==num) {
|
||||||
|
if (res(U8 *)&0x1FFFFF)
|
||||||
|
m=res;
|
||||||
|
else {
|
||||||
|
m->next=res->next;
|
||||||
|
goto am_done;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (i=(res(U8 *)&0x1FFFFF)>>MEM_PAG_BITS) {
|
||||||
|
j=1<<(21-MEM_PAG_BITS)-i;
|
||||||
|
if (res->pags<num+j)
|
||||||
|
m=res;
|
||||||
|
else if (res->pags==num+j) {
|
||||||
|
res->pags-=num;
|
||||||
|
res(U8 *)+=res->pags<<MEM_PAG_BITS;
|
||||||
|
res->pags=num;
|
||||||
|
goto am_done;
|
||||||
|
} else {
|
||||||
|
m1=res;
|
||||||
|
res(U8 *)+=j<<MEM_PAG_BITS;
|
||||||
|
res->pags=num;
|
||||||
|
m=res(U8 *)+num<<MEM_PAG_BITS;
|
||||||
|
m->pags=m1->pags-num-j;
|
||||||
|
m1->pags=j;
|
||||||
|
m->next=m1->next;
|
||||||
|
m1->next=m;
|
||||||
|
m->mb_signature=MBS_UNUSED_SIGNATURE_VAL;
|
||||||
|
goto am_done;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m=m->next=res(U8 *)+num<<MEM_PAG_BITS;
|
||||||
|
m->next=res->next;
|
||||||
|
m->pags=res->pags-num;
|
||||||
|
m->mb_signature=MBS_UNUSED_SIGNATURE_VAL;
|
||||||
|
res->pags=num;
|
||||||
|
goto am_done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
am_done:
|
||||||
|
i=num<<MEM_PAG_BITS;
|
||||||
|
bp->used_u8s+=i;
|
||||||
|
num>>=21-MEM_PAG_BITS;
|
||||||
|
*_pages2Meg=num;
|
||||||
|
m=res;
|
||||||
|
m1=m(U8 *)+i;
|
||||||
|
while (m<m1) {
|
||||||
|
pte=MemPageTable(m);
|
||||||
|
*pte &= ~0x18;
|
||||||
|
InvalidatePage(m);
|
||||||
|
m(U8 *)+=0x200000;
|
||||||
|
}
|
||||||
|
LBtr(&bp->locked_flags,BPlf_LOCKED);
|
||||||
|
POPFD
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
U8 *Mem2MegUncachedAlloc(I64 *_pages2Meg,CBlkPool *bp=NULL)
|
||||||
|
{/*Alloc 2Meg pages from BlkPool. Don't link to task.
|
||||||
|
(Linking to a task means they will be freed when the task dies.)
|
||||||
|
It will be marked uncached. It might give you more than you asked for
|
||||||
|
so a ptr to a page count is passed.
|
||||||
|
|
||||||
|
Return: NULL if out of memory.
|
||||||
|
*/
|
||||||
|
CMemBlk *res,*m,*m1;
|
||||||
|
I64 num=*_pages2Meg,*pte;
|
||||||
|
if (res=Mem2MegAlloc(_pages2Meg,bp)) {
|
||||||
|
num=*_pages2Meg;
|
||||||
|
m=res;
|
||||||
|
m1=m(U8 *)+num<<21;
|
||||||
|
while (m<m1) {
|
||||||
|
pte=MemPageTable(m);
|
||||||
|
*pte= *pte& ~0x18 |0x10;
|
||||||
|
InvalidatePage(m);
|
||||||
|
m(U8 *)+=0x200000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
U8 *Mem2MegWriteThruAlloc(I64 *_pages2Meg,CBlkPool *bp=NULL)
|
||||||
|
{/*Alloc 2Meg pages from BlkPool. Don't link to task.
|
||||||
|
(Linking to a task means they will be freed when the task dies.)
|
||||||
|
It will be marked write-through. It might give you more than you asked for
|
||||||
|
so a ptr to a page count is passed.
|
||||||
|
|
||||||
|
Return: NULL if out of memory.
|
||||||
|
*/
|
||||||
|
CMemBlk *res,*m,*m1;
|
||||||
|
I64 num=*_pages2Meg,*pte;
|
||||||
|
if (res=Mem2MegAlloc(_pages2Meg,bp)) {
|
||||||
|
num=*_pages2Meg;
|
||||||
|
m=res;
|
||||||
|
m1=m(U8 *)+num<<21;
|
||||||
|
while (m<m1) {
|
||||||
|
pte=MemPageTable(m);
|
||||||
|
*pte= *pte& ~0x18 |8;
|
||||||
|
InvalidatePage(m);
|
||||||
|
m(U8 *)+=0x200000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 Mem2MegFree(CMemBlk *m,I64 pages2Meg,CBlkPool *bp=NULL)
|
||||||
|
{//Return non-task 2Meg pages to BlkPool.
|
||||||
|
I64 *pte;
|
||||||
|
CMemBlk *m1,*m2;
|
||||||
|
if (m) {
|
||||||
|
if (!bp) bp=sys_code_bp;
|
||||||
|
m2=m;
|
||||||
|
m1=m(U8 *)+pages2Meg<<21;
|
||||||
|
while (m2<m1) {
|
||||||
|
pte=MemPageTable(m2);
|
||||||
|
*pte=*pte & ~0x18;
|
||||||
|
InvalidatePage(m2);
|
||||||
|
m2(U8 *)+=0x200000;
|
||||||
|
}
|
||||||
|
PUSHFD
|
||||||
|
CLI
|
||||||
|
while (LBts(&bp->locked_flags,BPlf_LOCKED))
|
||||||
|
PAUSE
|
||||||
|
m->mb_signature=MBS_UNUSED_SIGNATURE_VAL;
|
||||||
|
m->pags=pages2Meg<<(21-MEM_PAG_BITS);
|
||||||
|
bp->used_u8s-=pages2Meg<<21;
|
||||||
|
m->next=bp->mem_free_2meg_list;
|
||||||
|
bp->mem_free_2meg_list=m;
|
||||||
|
LBtr(&bp->locked_flags,BPlf_LOCKED);
|
||||||
|
POPFD
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CHeapCtrl *HeapCtrlBPInit(CBlkPool *bp,I64 pags)
|
||||||
|
{//Make mem chunk into HeapCtrl and BlkPool.
|
||||||
|
I64 num;
|
||||||
|
CMemBlk *m;
|
||||||
|
CHeapCtrl *hc;
|
||||||
|
MemSet(bp,0,sizeof(CBlkPool)+sizeof(CHeapCtrl));
|
||||||
|
hc=HeapCtrlInit(bp(U8 *)+sizeof(CBlkPool),,bp);
|
||||||
|
m=(bp(U8 *)+sizeof(CBlkPool)+sizeof(CHeapCtrl)+MEM_PAG_SIZE-1)&
|
||||||
|
~(MEM_PAG_SIZE-1);
|
||||||
|
num=(bp(U8 *)+pags<<MEM_PAG_BITS-m(U8 *))>>MEM_PAG_BITS;
|
||||||
|
bp->alloced_u8s=(pags-num)<<MEM_PAG_BITS;
|
||||||
|
BlkPoolAdd(bp,m,num);
|
||||||
|
return hc;
|
||||||
|
}
|
68
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/BeatFreq.ZC
Normal file
68
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/BeatFreq.ZC
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
Bool beat_done;
|
||||||
|
I64 start_buf_num;
|
||||||
|
U0 (*fp_task_end_cb)();
|
||||||
|
U0 (*fp_old_fill_buf)(SND_OUT_CONTAINER *buf,I64 buf_num)=NULL;
|
||||||
|
|
||||||
|
F64 freq1,freq2;
|
||||||
|
|
||||||
|
U0 BeatFillBuf(SND_OUT_CONTAINER *buf,I64 buf_num)
|
||||||
|
{ //Gets called by HD Audio task -- HDAudioTask().
|
||||||
|
I64 j,m;
|
||||||
|
F64 t;
|
||||||
|
if (beat_done) return;
|
||||||
|
t=ToF64((buf_num-start_buf_num)*(SND_BUF_LEN/SND_OCHANNELS))/SND_SAMPLE_RATE;
|
||||||
|
j=0;
|
||||||
|
while (j<SND_BUF_LEN) {
|
||||||
|
m=I32_MAX*(Sin(freq1*(2*ã)*t)+Sin(freq2*(2*ã)*t));
|
||||||
|
|
||||||
|
//Samples are 24-bit, placed in upper 24 bits of an I32.
|
||||||
|
m*=snd_vol;
|
||||||
|
buf[j++]=ToI64(m)&0xFFFFFF00; //Left
|
||||||
|
buf[j++]=ToI64(m)&0xFFFFFF00; //Right
|
||||||
|
|
||||||
|
t+=1.0/SND_SAMPLE_RATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 BeatTaskEndCB()
|
||||||
|
{
|
||||||
|
beat_done=TRUE;
|
||||||
|
fp_snd_fill_buf=fp_old_fill_buf;
|
||||||
|
if (fp_task_end_cb)
|
||||||
|
(*fp_task_end_cb)();
|
||||||
|
else
|
||||||
|
Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 BeatFreq()
|
||||||
|
{
|
||||||
|
if (snd_dev!=SD_HD_AUDIO) {
|
||||||
|
"Only works for HD Audio.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
freq1=600.0;
|
||||||
|
freq2=601.0;
|
||||||
|
beat_done=FALSE;
|
||||||
|
fp_task_end_cb=Fs->task_end_cb;
|
||||||
|
Fs->task_end_cb=&BeatTaskEndCB; //Catch <CTRL-ALT-X> or Kill() task
|
||||||
|
start_buf_num=snd_obuf_num;
|
||||||
|
fp_old_fill_buf=fp_snd_fill_buf;
|
||||||
|
fp_snd_fill_buf=&BeatFillBuf;
|
||||||
|
try {
|
||||||
|
"Pick two frequencies within a few Hz of each other to hear beats.\n"
|
||||||
|
"Pick two frequencies a multiple of two for an octave harmonic.\n"
|
||||||
|
"$$FG,GREEN$$<CTRL-ALT-C>$$FG$$ to exit.\n";
|
||||||
|
while (TRUE) {
|
||||||
|
freq1=PmtF64("Freq #1 (%0.2fHz):",freq1,20,20000);
|
||||||
|
freq2=PmtF64("Freq #2 (%0.2fHz):",freq2,20,20000);
|
||||||
|
}
|
||||||
|
} catch { //Catch <CTRL-ALT-C>, but pass it on to next higher handler.
|
||||||
|
fp_snd_fill_buf=fp_old_fill_buf;
|
||||||
|
Fs->task_end_cb=fp_task_end_cb;
|
||||||
|
}
|
||||||
|
beat_done=TRUE;
|
||||||
|
fp_snd_fill_buf=fp_old_fill_buf;
|
||||||
|
Fs->task_end_cb=fp_task_end_cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
BeatFreq;
|
16
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/Chords.ZC
Normal file
16
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/Chords.ZC
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
U0 Chords(Bool val=ON)
|
||||||
|
{
|
||||||
|
if (snd_dev!=SD_HD_AUDIO) {
|
||||||
|
"Only works for HD Audio.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
HDTonesInit;
|
||||||
|
if (val) {
|
||||||
|
hda.tone_swcs[1]->freq_multiplier=4.0/3.0;
|
||||||
|
hda.tone_swcs[1]->amp_multiplier=1.0;
|
||||||
|
hda.tone_swcs[2]->freq_multiplier=(4.0/3.0)`2;
|
||||||
|
hda.tone_swcs[2]->amp_multiplier=1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Chords(ON);
|
99
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/Echo.ZC
Normal file
99
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/Echo.ZC
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
Bool echo_done;
|
||||||
|
|
||||||
|
U0 (*fp_task_end_cb)();
|
||||||
|
U0 (*fp_old_fill_buf)(SND_OUT_CONTAINER *buf,I64 buf_num)=NULL;
|
||||||
|
U0 (*fp_old_copy_buf)(SND_IN_CONTAINER *buf,I64 buf_num)=NULL;
|
||||||
|
|
||||||
|
#define BUF_NUM 8
|
||||||
|
SND_IN_CONTAINER my_buf[SND_BUF_LEN*BUF_NUM];
|
||||||
|
|
||||||
|
I64 my_ibuf_ptr,my_obuf_ptr;
|
||||||
|
|
||||||
|
U0 EchoFillBuf(SND_OUT_CONTAINER *buf,I64)
|
||||||
|
{
|
||||||
|
I64 j;
|
||||||
|
if (echo_done) return;
|
||||||
|
j=0;
|
||||||
|
while (j<SND_BUF_LEN) {
|
||||||
|
buf[j++]=ToI64(snd_vol*my_buf[my_obuf_ptr++
|
||||||
|
&(SND_BUF_LEN*BUF_NUM-1)])<<16&0xFFFFFF00;
|
||||||
|
buf[j++]=ToI64(snd_vol*my_buf[my_obuf_ptr++
|
||||||
|
&(SND_BUF_LEN*BUF_NUM-1)])<<16&0xFFFFFF00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 EchoCopyBuf(SND_IN_CONTAINER *buf,I64)
|
||||||
|
{
|
||||||
|
I64 j;
|
||||||
|
if (echo_done) return;
|
||||||
|
j=0;
|
||||||
|
while (j<SND_BUF_LEN) {
|
||||||
|
my_buf[my_ibuf_ptr++ &(SND_BUF_LEN*BUF_NUM-1)]=buf[j++];
|
||||||
|
my_buf[my_ibuf_ptr++ &(SND_BUF_LEN*BUF_NUM-1)]=buf[j++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 EchoTaskEndCB()
|
||||||
|
{
|
||||||
|
echo_done=TRUE;
|
||||||
|
HDStop(TRUE,FALSE);
|
||||||
|
fp_snd_fill_buf=fp_old_fill_buf;
|
||||||
|
fp_snd_copy_buf=fp_old_copy_buf;
|
||||||
|
if (fp_task_end_cb)
|
||||||
|
(*fp_task_end_cb)();
|
||||||
|
else
|
||||||
|
Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 DrawIt(CTask *task,CDC *dc)
|
||||||
|
{
|
||||||
|
SND_IN_CONTAINER *buf=hda.istr0_buf[0];
|
||||||
|
I64 i,x1,y1,x2=0,y2=0,
|
||||||
|
cy=task->pix_height>>1;
|
||||||
|
dc->color=BLUE;
|
||||||
|
for (i=0;i<SND_BUF_LEN;i++) {
|
||||||
|
x1=i*task->pix_width/SND_BUF_LEN;
|
||||||
|
y1=cy-buf[i]*cy/I16_MAX;
|
||||||
|
GrLine(dc,x2,y2,x1,y1);
|
||||||
|
x2=x1;
|
||||||
|
y2=y1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 EchoDemo()
|
||||||
|
{
|
||||||
|
if (snd_dev!=SD_HD_AUDIO) {
|
||||||
|
"Only works for HD Audio.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
|
||||||
|
HDRun(TRUE,TRUE);
|
||||||
|
echo_done=FALSE;
|
||||||
|
fp_task_end_cb=Fs->task_end_cb;
|
||||||
|
Fs->task_end_cb=&EchoTaskEndCB; //Catch <CTRL-ALT-X> or Kill() task
|
||||||
|
my_ibuf_ptr=(BUF_NUM/2)*SND_BUF_LEN;
|
||||||
|
my_obuf_ptr=0;
|
||||||
|
fp_old_fill_buf=fp_snd_fill_buf;
|
||||||
|
fp_old_copy_buf=fp_snd_copy_buf;
|
||||||
|
fp_snd_fill_buf=&EchoFillBuf;
|
||||||
|
fp_snd_copy_buf=&EchoCopyBuf;
|
||||||
|
DocCursor;
|
||||||
|
DocClear;
|
||||||
|
Fs->draw_it=&DrawIt;
|
||||||
|
try
|
||||||
|
CharGet;
|
||||||
|
catch { //Catch <CTRL-ALT-C>, but pass it on to next higher handler.
|
||||||
|
fp_snd_fill_buf=fp_old_fill_buf;
|
||||||
|
fp_snd_copy_buf=fp_old_copy_buf;
|
||||||
|
Fs->task_end_cb=fp_task_end_cb;
|
||||||
|
}
|
||||||
|
echo_done=TRUE;
|
||||||
|
HDStop(TRUE,FALSE);
|
||||||
|
fp_snd_fill_buf=fp_old_fill_buf;
|
||||||
|
fp_snd_copy_buf=fp_old_copy_buf;
|
||||||
|
Fs->task_end_cb=fp_task_end_cb;
|
||||||
|
SettingsPop;
|
||||||
|
}
|
||||||
|
|
||||||
|
EchoDemo;
|
||||||
|
|
17
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/Guitar.ZC
Normal file
17
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/Guitar.ZC
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
U0 Guitar(Bool val=ON,F64 à=0.7)
|
||||||
|
{
|
||||||
|
I64 i;
|
||||||
|
F64 m;
|
||||||
|
if (snd_dev!=SD_HD_AUDIO) {
|
||||||
|
"Only works for HD Audio.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
HDTonesInit;
|
||||||
|
if (val)
|
||||||
|
for (i=0,m=1.0;i<HD_TONES;i++,m*=à) {
|
||||||
|
hda.tone_swcs[i]->freq_multiplier=i+1;
|
||||||
|
hda.tone_swcs[i]->amp_multiplier=m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Guitar(ON);
|
96
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/PolyPhonic.ZC
Normal file
96
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/PolyPhonic.ZC
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
Bool poly_done;
|
||||||
|
I64 start_buf_num;
|
||||||
|
U0 (*fp_task_end_cb)();
|
||||||
|
U0 (*fp_old_fill_buf)(SND_OUT_CONTAINER *buf,I64 buf_num)=NULL;
|
||||||
|
|
||||||
|
U0 PolyFillBuf(SND_OUT_CONTAINER *buf,I64 buf_num)
|
||||||
|
{ //Gets called by HD Audio task -- HDAudioTask().
|
||||||
|
|
||||||
|
//Note: the buffer is in uncached memory
|
||||||
|
//so you might want to avoid multiple
|
||||||
|
//accesses due to slow speed. (If you were
|
||||||
|
//to add a bunch of waveforms together, you
|
||||||
|
//might want to do it in a cached buffer
|
||||||
|
//and copy it once.)
|
||||||
|
|
||||||
|
I64 j,m,r;
|
||||||
|
F64 t,d;
|
||||||
|
if (poly_done) return;
|
||||||
|
t=ToF64((buf_num-start_buf_num)*(SND_BUF_LEN/SND_OCHANNELS))/SND_SAMPLE_RATE;
|
||||||
|
j=0;
|
||||||
|
while (j<SND_BUF_LEN) {
|
||||||
|
d=0.5*Sin(1.0*(2*ã)*t)+0.5; //Stereo pos from 0.0-1.0
|
||||||
|
r=RandI32;
|
||||||
|
m=0;
|
||||||
|
|
||||||
|
m+=0.2*I32_MAX*Caw(t,0.25)*Sin(220.0*(2*ã)*t);
|
||||||
|
m+=0.2*I32_MAX*Caw(t,0.25)*Sin(222.0*(2*ã)*t);
|
||||||
|
m+=0.2*I32_MAX*Caw(t,0.25)*Sin(880.0*(2*ã)*t);
|
||||||
|
m+=0.2*I32_MAX*Caw(t,0.25)*Sin(884.0*(2*ã)*t);
|
||||||
|
m+=0.4*r*Caw(t,.125);
|
||||||
|
if (Caw(t-.25,0.5)<=0.05)
|
||||||
|
m+=0.3*r*Caw(t,0.05);
|
||||||
|
if (t>4.0) {
|
||||||
|
if (0.90<Caw(t,1.0))
|
||||||
|
m+=0.6*I32_MAX*Caw(t,0.1)*FullCaw(t,0.001);
|
||||||
|
if (t>8.0) {
|
||||||
|
if (0.70<Caw(t,1.0)<0.90)
|
||||||
|
m+=0.4*I32_MAX*Caw(t-.7,0.5)*FullCaw(t,0.00075);
|
||||||
|
if (t>12.0) {
|
||||||
|
if (0.30<Caw(t,1.0)<0.40)
|
||||||
|
m+=0.4*I32_MAX*Sin(100.0/(1.1-Saw(t,0.01)));
|
||||||
|
if (t>16.0)
|
||||||
|
m+=0.3*I32_MAX*Caw(t,1.0/6)*Sin(440.0*(2*ã)*t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Samples are 24-bit, placed in upper 24 bits of an I32.
|
||||||
|
m*=snd_vol;
|
||||||
|
buf[j++]=ToI64(m*d)&0xFFFFFF00; //Left
|
||||||
|
buf[j++]=ToI64(m*(1.0-d))&0xFFFFFF00; //Right
|
||||||
|
|
||||||
|
t+=1.0/SND_SAMPLE_RATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 PolyTaskEndCB()
|
||||||
|
{
|
||||||
|
poly_done=TRUE;
|
||||||
|
fp_snd_fill_buf=fp_old_fill_buf;
|
||||||
|
if (fp_task_end_cb)
|
||||||
|
(*fp_task_end_cb)();
|
||||||
|
else
|
||||||
|
Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 PolyPhonic()
|
||||||
|
{
|
||||||
|
if (snd_dev!=SD_HD_AUDIO) {
|
||||||
|
"Only works for HD Audio.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
poly_done=FALSE;
|
||||||
|
fp_task_end_cb=Fs->task_end_cb;
|
||||||
|
Fs->task_end_cb=&PolyTaskEndCB; //Catch <CTRL-ALT-X> or Kill() task
|
||||||
|
start_buf_num=snd_obuf_num;
|
||||||
|
fp_old_fill_buf=fp_snd_fill_buf;
|
||||||
|
fp_snd_fill_buf=&PolyFillBuf;
|
||||||
|
try
|
||||||
|
#if __CMD_LINE__
|
||||||
|
PressAKey;
|
||||||
|
#else
|
||||||
|
View;
|
||||||
|
#endif
|
||||||
|
catch { //Catch <CTRL-ALT-C>, but pass it on to next higher handler.
|
||||||
|
fp_snd_fill_buf=fp_old_fill_buf;
|
||||||
|
Fs->task_end_cb=fp_task_end_cb;
|
||||||
|
}
|
||||||
|
poly_done=TRUE;
|
||||||
|
fp_snd_fill_buf=fp_old_fill_buf;
|
||||||
|
Fs->task_end_cb=fp_task_end_cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __CMD_LINE__
|
||||||
|
PolyPhonic;
|
||||||
|
#endif
|
117
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/Record.ZC
Normal file
117
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/Record.ZC
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
Bool record_stop,record_done;
|
||||||
|
|
||||||
|
U0 (*fp_old_copy_buf)(SND_IN_CONTAINER *buf,I64 buf_num)=NULL;
|
||||||
|
|
||||||
|
#define RECORD_BUF_SIZE (SND_BUF_LEN*0x100)
|
||||||
|
|
||||||
|
SND_IN_CONTAINER *record_buf[2];
|
||||||
|
I64 record_buf_iptr,record_ibuf_num,record_obuf_num;
|
||||||
|
|
||||||
|
U0 RecordCopyBuf(SND_IN_CONTAINER *buf,I64)
|
||||||
|
{
|
||||||
|
I64 j;
|
||||||
|
SND_IN_CONTAINER *_s=record_buf[record_ibuf_num&1];
|
||||||
|
j=0;
|
||||||
|
while (j<SND_BUF_LEN) {
|
||||||
|
_s[record_buf_iptr++]=buf[j++];
|
||||||
|
j++; //Record in mono
|
||||||
|
}
|
||||||
|
if (record_buf_iptr>=RECORD_BUF_SIZE) {
|
||||||
|
record_buf_iptr=0;
|
||||||
|
record_ibuf_num++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 DrawIt(CTask *task,CDC *dc)
|
||||||
|
{
|
||||||
|
SND_IN_CONTAINER *buf=hda.istr0_buf[0];
|
||||||
|
I64 i,x1,y1,x2=0,y2=0,
|
||||||
|
cy=task->pix_height>>1;
|
||||||
|
dc->color=BLUE;
|
||||||
|
for (i=0;i<SND_BUF_LEN;i++) {
|
||||||
|
x1=i*task->pix_width/SND_BUF_LEN;
|
||||||
|
y1=cy-buf[i]*cy/I16_MAX;
|
||||||
|
GrLine(dc,x2,y2,x1,y1);
|
||||||
|
x2=x1;
|
||||||
|
y2=y1;
|
||||||
|
}
|
||||||
|
dc->color=RED;
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 RecordTaskEndCB()
|
||||||
|
{
|
||||||
|
fp_snd_copy_buf=fp_old_copy_buf;
|
||||||
|
HDStop(TRUE,FALSE);
|
||||||
|
Free(record_buf[0]);
|
||||||
|
Free(record_buf[1]);
|
||||||
|
record_done=TRUE;
|
||||||
|
Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 RecordTask(U8 *filename)
|
||||||
|
{
|
||||||
|
Bool old_io_snd;
|
||||||
|
U8 *filename=StrNew(filename),*filename2;
|
||||||
|
TaskInitExt; //needed for disk access
|
||||||
|
record_buf[0]=CAlloc(RECORD_BUF_SIZE*sizeof(SND_IN_CONTAINER));
|
||||||
|
record_buf[1]=CAlloc(RECORD_BUF_SIZE*sizeof(SND_IN_CONTAINER));
|
||||||
|
FileExtRemove(filename);
|
||||||
|
record_buf_iptr=0;
|
||||||
|
record_ibuf_num=0;
|
||||||
|
record_obuf_num=0;
|
||||||
|
record_done=FALSE;
|
||||||
|
Fs->task_end_cb=&RecordTaskEndCB;
|
||||||
|
fp_old_copy_buf=fp_snd_copy_buf;
|
||||||
|
fp_snd_copy_buf=&RecordCopyBuf;
|
||||||
|
HDRun(TRUE,FALSE);
|
||||||
|
old_io_snd=IOSnd(OFF);
|
||||||
|
while (!record_stop) {
|
||||||
|
if (record_ibuf_num>record_obuf_num) {
|
||||||
|
filename2=MPrint("%s%04d.SNZ",filename,record_obuf_num);
|
||||||
|
SndFileWrite(filename2,record_buf[record_obuf_num&1],RECORD_BUF_SIZE);
|
||||||
|
record_obuf_num++;
|
||||||
|
Free(filename2);
|
||||||
|
}
|
||||||
|
Sleep(1);
|
||||||
|
}
|
||||||
|
filename2=MPrint("%s%04d.SNZ",filename,record_obuf_num);
|
||||||
|
SndFileWrite(filename2,record_buf[record_obuf_num&1],record_buf_iptr);
|
||||||
|
record_obuf_num++;
|
||||||
|
Free(filename2);
|
||||||
|
Free(filename);
|
||||||
|
IOSnd(old_io_snd);
|
||||||
|
record_done=TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 RecordDemo(U8 *filename="~/Record.SNZ")
|
||||||
|
{
|
||||||
|
if (snd_dev!=SD_HD_AUDIO) {
|
||||||
|
"Only works for HD Audio.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
record_done=FALSE;
|
||||||
|
record_stop=FALSE;
|
||||||
|
Spawn(&RecordTask,filename,"Record .SNZ",,Fs);
|
||||||
|
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
|
||||||
|
DocCursor;
|
||||||
|
DocClear;
|
||||||
|
Fs->draw_it=&DrawIt;
|
||||||
|
try
|
||||||
|
CharGet;
|
||||||
|
catch //Catch <CTRL-ALT-C>, but pass it on to next higher handler.
|
||||||
|
record_stop=TRUE;
|
||||||
|
record_stop=TRUE;
|
||||||
|
while (record_done)
|
||||||
|
Yield;
|
||||||
|
SettingsPop;
|
||||||
|
while (TRUE) {
|
||||||
|
"\n\nPlay ";
|
||||||
|
if (YorN)
|
||||||
|
SndFilePlaySeq(filename,record_obuf_num);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
NewLine(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
RecordDemo;
|
44
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/SndScope.ZC
Normal file
44
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/SndScope.ZC
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
U0 DrawIt(CTask *task,CDC *dc)
|
||||||
|
{
|
||||||
|
SND_OUT_CONTAINER *buf=hda.ostr0_buf[0];
|
||||||
|
I64 i,x1,y1,x2,y2,
|
||||||
|
cy=task->pix_height>>1;
|
||||||
|
|
||||||
|
dc->color=BLUE;
|
||||||
|
x2=0;y2=cy;
|
||||||
|
for (i=0;i<SND_BUF_LEN;i+=2) {
|
||||||
|
x1=i*task->pix_width/SND_BUF_LEN;
|
||||||
|
y1=cy-buf[i]*cy/snd_vol/I32_MAX;
|
||||||
|
GrLine(dc,x2,y2,x1,y1);
|
||||||
|
x2=x1;y2=y1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dc->color=GREEN;
|
||||||
|
x2=0;y2=cy;
|
||||||
|
for (i=1;i<SND_BUF_LEN;i+=2) {
|
||||||
|
x1=i*task->pix_width/SND_BUF_LEN;
|
||||||
|
y1=cy-buf[i]*cy/snd_vol/I32_MAX;
|
||||||
|
GrLine(dc,x2,y2,x1,y1);
|
||||||
|
x2=x1; y2=y1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 SndScope()
|
||||||
|
{
|
||||||
|
if (snd_dev!=SD_HD_AUDIO) {
|
||||||
|
"Only works for HD Audio.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
|
||||||
|
WinHorz(1,18);
|
||||||
|
WinVert(15,TEXT_ROWS-2);
|
||||||
|
DocCursor;
|
||||||
|
DocClear;
|
||||||
|
Fs->draw_it=&DrawIt;
|
||||||
|
CharGet;
|
||||||
|
SettingsPop;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __CMD_LINE__
|
||||||
|
SndScope;
|
||||||
|
#endif
|
280
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/Synth.ZC
Normal file
280
src/Home/Sound/HDAudio1/Sup1HDAudio/Examples/Synth.ZC
Normal file
|
@ -0,0 +1,280 @@
|
||||||
|
#define M_WAVEFORM 0
|
||||||
|
#define M_FREQUENCY 1
|
||||||
|
#define M_ENVELOPE 2
|
||||||
|
|
||||||
|
#define M_MODES_NUM 3
|
||||||
|
|
||||||
|
I64 mode;
|
||||||
|
Bool my_ms_down;
|
||||||
|
I64 last_x,last_y;
|
||||||
|
|
||||||
|
Bool synth_done;
|
||||||
|
|
||||||
|
U0 (*fp_task_end_cb)();
|
||||||
|
U0 (*fp_old_fill_buf)(SND_OUT_CONTAINER *buf,I64 buf_num)=NULL;
|
||||||
|
|
||||||
|
#define BUF_NUM 8
|
||||||
|
SND_OUT_CONTAINER my_buf[SND_BUF_LEN*BUF_NUM];
|
||||||
|
|
||||||
|
#define WF_BUF_LEN 2048
|
||||||
|
#define WF_Y_SCALE 2048.0
|
||||||
|
I64 waveform_buf[WF_BUF_LEN];
|
||||||
|
|
||||||
|
#define FQ_BUF_LEN 2048
|
||||||
|
#define FQ_Y_SCALE 2048.0
|
||||||
|
I64 frequency_buf[FQ_BUF_LEN];
|
||||||
|
F64 fq_scale;
|
||||||
|
|
||||||
|
#define EL_BUF_LEN 2048
|
||||||
|
#define EL_Y_SCALE 2048.0
|
||||||
|
I64 envelope_buf[EL_BUF_LEN];
|
||||||
|
F64 el_scale;
|
||||||
|
|
||||||
|
U0 SynthFillBuf(SND_OUT_CONTAINER *buf,I64 buf_num)
|
||||||
|
{
|
||||||
|
I64 i,j,l,k0,k1,k2,k3;
|
||||||
|
F64 d;
|
||||||
|
static F64 k=0;
|
||||||
|
if (synth_done) return;
|
||||||
|
j=0;
|
||||||
|
k0=buf_num*(SND_BUF_LEN/SND_OCHANNELS);
|
||||||
|
while (j<SND_BUF_LEN) {
|
||||||
|
k1=WF_BUF_LEN*k/(SND_BUF_LEN/SND_OCHANNELS);
|
||||||
|
k2=fq_scale*FQ_BUF_LEN*k0/(SND_BUF_LEN/SND_OCHANNELS);
|
||||||
|
k3=el_scale*EL_BUF_LEN*k0/(SND_BUF_LEN/SND_OCHANNELS);
|
||||||
|
|
||||||
|
d=envelope_buf[k3%EL_BUF_LEN]/EL_Y_SCALE;
|
||||||
|
d*=snd_vol;
|
||||||
|
d*=I32_MAX*waveform_buf[k1%WF_BUF_LEN]/WF_Y_SCALE;
|
||||||
|
i=ToI64(d)&0xFFFFFF00;
|
||||||
|
|
||||||
|
for (l=0;l<SND_OCHANNELS;l++)
|
||||||
|
buf[j++]=i;
|
||||||
|
|
||||||
|
d=frequency_buf[k2%FQ_BUF_LEN]/FQ_Y_SCALE; // [0.0,1.0]
|
||||||
|
d=(SND_BUF_LEN/SND_OCHANNELS)*Exp(5.0*d+4)/SND_SAMPLE_RATE;
|
||||||
|
k+=d;
|
||||||
|
k0++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 SynthTaskEndCB()
|
||||||
|
{
|
||||||
|
synth_done=TRUE;
|
||||||
|
HDStop(TRUE,FALSE);
|
||||||
|
fp_snd_fill_buf=fp_old_fill_buf;
|
||||||
|
if (fp_task_end_cb)
|
||||||
|
(*fp_task_end_cb)();
|
||||||
|
else
|
||||||
|
Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool WFPlot(U8 *,I64 x,I64 y,I64)
|
||||||
|
{
|
||||||
|
if (0<=x<=WF_BUF_LEN)
|
||||||
|
waveform_buf[x]=y;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool FQPlot(U8 *,I64 x,I64 y,I64)
|
||||||
|
{
|
||||||
|
if (0<=x<=FQ_BUF_LEN)
|
||||||
|
frequency_buf[x]=AbsI64(y);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool ELPlot(U8 *,I64 x,I64 y,I64)
|
||||||
|
{
|
||||||
|
if (0<=x<=EL_BUF_LEN)
|
||||||
|
envelope_buf[x]=AbsI64(y);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 DrawIt(CTask *task,CDC *dc)
|
||||||
|
{
|
||||||
|
I64 i,x1,y1,x2,y2,
|
||||||
|
cy=task->pix_height>>1,
|
||||||
|
h_max=task->pix_width-1;
|
||||||
|
|
||||||
|
if (!winmgr.show_menu) {
|
||||||
|
if (mouse.lb) {
|
||||||
|
if (my_ms_down)
|
||||||
|
switch (mode) {
|
||||||
|
case M_WAVEFORM:
|
||||||
|
Line(NULL,
|
||||||
|
(last_x-task->pix_left-task->scroll_x)*WF_BUF_LEN/h_max,
|
||||||
|
WF_Y_SCALE*(cy-last_y+task->pix_top+task->scroll_y)/cy,0,
|
||||||
|
( msx-task->pix_left-task->scroll_x)*WF_BUF_LEN/h_max,
|
||||||
|
WF_Y_SCALE*(cy-msy+task->pix_top+task->scroll_y)/cy,0,
|
||||||
|
&WFPlot);
|
||||||
|
break;
|
||||||
|
case M_FREQUENCY:
|
||||||
|
Line(NULL,
|
||||||
|
(last_x-task->pix_left-task->scroll_x)*FQ_BUF_LEN/h_max,
|
||||||
|
FQ_Y_SCALE*(cy-last_y+task->pix_top+task->scroll_y)/cy,0,
|
||||||
|
( msx-task->pix_left-task->scroll_x)*FQ_BUF_LEN/h_max,
|
||||||
|
FQ_Y_SCALE*(cy-msy+task->pix_top+task->scroll_y)/cy,0,
|
||||||
|
&FQPlot);
|
||||||
|
break;
|
||||||
|
case M_ENVELOPE:
|
||||||
|
Line(NULL,
|
||||||
|
(last_x-task->pix_left-task->scroll_x)*EL_BUF_LEN/h_max,
|
||||||
|
EL_Y_SCALE*(cy-last_y+task->pix_top+task->scroll_y)/cy,0,
|
||||||
|
( msx-task->pix_left-task->scroll_x)*EL_BUF_LEN/h_max,
|
||||||
|
EL_Y_SCALE*(cy-msy+task->pix_top+task->scroll_y)/cy,0,
|
||||||
|
&ELPlot);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
my_ms_down=TRUE;
|
||||||
|
last_x=msx;
|
||||||
|
last_y=msy;
|
||||||
|
} else
|
||||||
|
my_ms_down=FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
x2=-1;
|
||||||
|
if (mode==M_WAVEFORM && Blink) {
|
||||||
|
dc->color=ROPF_DITHER+WHITE<<16+RED;
|
||||||
|
GrPrint(dc,0,cy-FONT_HEIGHT,"Set Waveform.");
|
||||||
|
} else
|
||||||
|
dc->color=RED;
|
||||||
|
for (i=0;i<WF_BUF_LEN;i++) {
|
||||||
|
x1=i*task->pix_width/WF_BUF_LEN;
|
||||||
|
y1=cy-cy*waveform_buf[i]/WF_Y_SCALE;
|
||||||
|
if (x2>=0)
|
||||||
|
GrLine(dc,x2,y2,x1,y1);
|
||||||
|
x2=x1;
|
||||||
|
y2=y1;
|
||||||
|
}
|
||||||
|
|
||||||
|
x2=-1;
|
||||||
|
if (mode==M_FREQUENCY && Blink) {
|
||||||
|
dc->color=ROPF_DITHER+WHITE<<16+BLUE;
|
||||||
|
GrPrint(dc,0,cy-FONT_HEIGHT,"Set Frequency.");
|
||||||
|
} else
|
||||||
|
dc->color=BLUE;
|
||||||
|
for (i=0;i<FQ_BUF_LEN;i++) {
|
||||||
|
x1=i*task->pix_width/FQ_BUF_LEN;
|
||||||
|
y1=cy-cy*frequency_buf[i]/FQ_Y_SCALE;
|
||||||
|
if (x2>=0)
|
||||||
|
GrLine(dc,x2,y2,x1,y1);
|
||||||
|
GrLine(dc,x2,cy-(y2-cy),x1,cy-(y1-cy));
|
||||||
|
x2=x1;
|
||||||
|
y2=y1;
|
||||||
|
}
|
||||||
|
|
||||||
|
x2=-1;
|
||||||
|
if (mode==M_ENVELOPE && Blink) {
|
||||||
|
dc->color=ROPF_DITHER+WHITE<<16+GREEN;
|
||||||
|
GrPrint(dc,0,cy-FONT_HEIGHT,"Set Envelope.");
|
||||||
|
} else
|
||||||
|
dc->color=GREEN;
|
||||||
|
for (i=0;i<EL_BUF_LEN;i++) {
|
||||||
|
x1=i*task->pix_width/EL_BUF_LEN;
|
||||||
|
y1=cy-cy*envelope_buf[i]/EL_Y_SCALE;
|
||||||
|
if (x2>=0)
|
||||||
|
GrLine(dc,x2,y2,x1,y1);
|
||||||
|
GrLine(dc,x2,cy-(y2-cy),x1,cy-(y1-cy));
|
||||||
|
x2=x1;
|
||||||
|
y2=y1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dc->color=BLACK;
|
||||||
|
GrLine(dc,0,cy,task->pix_width,cy);
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 SetMenu()
|
||||||
|
{
|
||||||
|
MenuEntryFind(Fs->cur_menu,"Mode/Waveform")->checked=mode==M_WAVEFORM;
|
||||||
|
MenuEntryFind(Fs->cur_menu,"Mode/Frequency")->checked=mode==M_FREQUENCY;
|
||||||
|
MenuEntryFind(Fs->cur_menu,"Mode/Envelope")->checked=mode==M_ENVELOPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 Init()
|
||||||
|
{
|
||||||
|
my_ms_down=FALSE;
|
||||||
|
mode=M_WAVEFORM;
|
||||||
|
MemSetI64(&waveform_buf[0] ,-0.5 *WF_Y_SCALE,WF_BUF_LEN/2);
|
||||||
|
MemSetI64(&waveform_buf[WF_BUF_LEN/2] , 0.5 *WF_Y_SCALE,WF_BUF_LEN/2);
|
||||||
|
MemSetI64(frequency_buf , 0.25*FQ_Y_SCALE,FQ_BUF_LEN);
|
||||||
|
MemSetI64(envelope_buf , 0.75*EL_Y_SCALE,EL_BUF_LEN);
|
||||||
|
fq_scale=0.02;
|
||||||
|
el_scale=0.02;
|
||||||
|
SetMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 Synth()
|
||||||
|
{
|
||||||
|
I64 arg1,arg2;
|
||||||
|
if (snd_dev!=SD_HD_AUDIO) {
|
||||||
|
"Only works for HD Audio.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
|
||||||
|
MenuPush(
|
||||||
|
"File {"
|
||||||
|
" New(,'\n');"
|
||||||
|
" Abort(,CH_SHIFT_ESC);"
|
||||||
|
" Exit(,CH_ESC);"
|
||||||
|
"}"
|
||||||
|
"Mode {"
|
||||||
|
" Waveform(,'1');"
|
||||||
|
" Frequency(,'2');"
|
||||||
|
" Envelope(,'3');"
|
||||||
|
"}"
|
||||||
|
);
|
||||||
|
AutoComplete;
|
||||||
|
WinBorder;
|
||||||
|
WinMax;
|
||||||
|
DocCursor;
|
||||||
|
DocClear;
|
||||||
|
Fs->win_inhibit=WIG_TASK_DEFAULT-WIF_SELF_FOCUS-WIF_FOCUS_TASK_MENU;
|
||||||
|
|
||||||
|
Init;
|
||||||
|
|
||||||
|
synth_done=FALSE;
|
||||||
|
fp_task_end_cb=Fs->task_end_cb;
|
||||||
|
Fs->task_end_cb=&SynthTaskEndCB; //Catch <CTRL-ALT-X> or Kill() task
|
||||||
|
fp_old_fill_buf=fp_snd_fill_buf;
|
||||||
|
fp_snd_fill_buf=&SynthFillBuf;
|
||||||
|
Fs->draw_it=&DrawIt;
|
||||||
|
try {
|
||||||
|
while (TRUE) {
|
||||||
|
switch (MessageGet(&arg1,&arg2,1<<MESSAGE_KEY_DOWN+1<<MESSAGE_MS_R_DOWN)) {
|
||||||
|
case MESSAGE_KEY_DOWN:
|
||||||
|
switch (arg1) {
|
||||||
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
mode=arg1-'1';
|
||||||
|
SetMenu;
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
Init;
|
||||||
|
break;
|
||||||
|
case CH_SHIFT_ESC:
|
||||||
|
case CH_ESC:
|
||||||
|
goto sy_done;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MESSAGE_MS_R_DOWN:
|
||||||
|
if (++mode==M_MODES_NUM)
|
||||||
|
mode=0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sy_done:
|
||||||
|
MessageGet(,,1<<MESSAGE_KEY_UP);
|
||||||
|
} catch { //Catch <CTRL-ALT-C>, but pass it on to next higher handler.
|
||||||
|
fp_snd_fill_buf=fp_old_fill_buf;
|
||||||
|
Fs->task_end_cb=fp_task_end_cb;
|
||||||
|
}
|
||||||
|
synth_done=TRUE;
|
||||||
|
fp_snd_fill_buf=fp_old_fill_buf;
|
||||||
|
Fs->task_end_cb=fp_task_end_cb;
|
||||||
|
SettingsPop;
|
||||||
|
}
|
||||||
|
|
||||||
|
Synth;
|
||||||
|
|
697
src/Home/Sound/HDAudio1/Sup1HDAudio/HDAudio.ZC
Normal file
697
src/Home/Sound/HDAudio1/Sup1HDAudio/HDAudio.ZC
Normal file
|
@ -0,0 +1,697 @@
|
||||||
|
//SysFile("~/sup1hdaudio/Sup1CodeScraps/Mem/Mem2Meg.ZC");
|
||||||
|
|
||||||
|
#
|
||||||
|
help_index "Sound/HDAudio"
|
||||||
|
|
||||||
|
//snd devs
|
||||||
|
#define SD_PC_SPEAKER 0
|
||||||
|
#define SD_HD_AUDIO 1
|
||||||
|
#define SND_SAMPLE_RATE 48000
|
||||||
|
#define SND_SAMPLE_BITS 24
|
||||||
|
#define SND_OCHANNELS 2
|
||||||
|
#define SND_ICHANNELS 2
|
||||||
|
#define SND_OUT_CONTAINER I32
|
||||||
|
#define SND_IN_CONTAINER I16
|
||||||
|
#define SND_BUF_LEN 0x400
|
||||||
|
#define SND_BUF_TIME_mS(SND_BUF_LEN / SND_OCHANNELS *1000.0 / \
|
||||||
|
SND_SAMPLE_RATE)
|
||||||
|
|
||||||
|
F64 snd_freq = 0;
|
||||||
|
I64 snd_dev = SD_PC_SPEAKER;
|
||||||
|
Bool snd_record = FALSE;
|
||||||
|
F64 snd_vol = 0.1;
|
||||||
|
U0(*fp_snd)(F64 freq, I64 waveform, F64 amp) = NULL;
|
||||||
|
U0(*fp_snd_record)(F64 freq, I64 waveform, F64 amp) = NULL;
|
||||||
|
U0(*fp_snd_fill_buf)(SND_OUT_CONTAINER *buf, I64 buf_num) = NULL;
|
||||||
|
U0(*fp_snd_copy_buf)(SND_IN_CONTAINER *buf, I64 buf_num) = NULL;
|
||||||
|
|
||||||
|
I64 snd_obuf_num, snd_ibuf_num;
|
||||||
|
|
||||||
|
#define Sf_FILLING_OUT 0
|
||||||
|
I64 snd_flags;
|
||||||
|
|
||||||
|
#define HD_1_CHAN 0
|
||||||
|
#define HD_2_CHAN 1
|
||||||
|
#define HD_3_CHAN 2
|
||||||
|
#define HD_4_CHAN 3
|
||||||
|
#define HD_8_BIT 0
|
||||||
|
#define HD_16_BIT 1
|
||||||
|
#define HD_20_BIT 2
|
||||||
|
#define HD_24_BIT 3
|
||||||
|
#define HD_32_BIT 4
|
||||||
|
#define HD_48kHz 0
|
||||||
|
#define HD_DFT_OUT_FMT(HD_2_CHAN + HD_24_BIT << 4 + HD_48kHz << 8)
|
||||||
|
#define HD_DFT_IN_FMT(HD_2_CHAN + HD_16_BIT << 4 + HD_48kHz << 8)
|
||||||
|
#define HD_POS_BUF_MULTIPLES 0x1000
|
||||||
|
#define HD_CORB_ENTRIES 256
|
||||||
|
#define HD_RIRB_ENTRIES 256
|
||||||
|
#define HD_BDL_ENTRIES 256
|
||||||
|
#define HD_GCTL 0x08
|
||||||
|
#define HD_STATESTS 0x0E
|
||||||
|
#define HD_GSTS 0x10
|
||||||
|
#define HD_CORBLBASE 0x40
|
||||||
|
#define HD_CORBUBASE 0x44
|
||||||
|
#define HD_CORBWP 0x48
|
||||||
|
#define HD_CORBRP 0x4A
|
||||||
|
#define HD_CORBCTL 0x4C
|
||||||
|
#define HD_CORBST 0x4D
|
||||||
|
#define HD_RIRBLBASE 0x50
|
||||||
|
#define HD_RIRBUBASE 0x54
|
||||||
|
#define HD_RIRBWP 0x58
|
||||||
|
#define HD_RIRBCTL 0x5C
|
||||||
|
#define HD_RIRBSTS 0x5D
|
||||||
|
#define STRCTL 0x00
|
||||||
|
#define STRSTS 0x03
|
||||||
|
#define STRLPIB 0x04
|
||||||
|
#define STRCBL 0x08
|
||||||
|
#define STRLVI 0x0C
|
||||||
|
#define STRFIFOW 0x0E
|
||||||
|
#define STRFIFOS 0x10
|
||||||
|
#define STRFMT 0x12
|
||||||
|
#define STRBDPL 0x18
|
||||||
|
#define STRBDPU 0x1C
|
||||||
|
#define ISTR0 0x080
|
||||||
|
#define ISTR1 0x0A0
|
||||||
|
#define ISTR2 0x0C0
|
||||||
|
#define ISTR3 0x0E0
|
||||||
|
#define OSTR0 0x100
|
||||||
|
#define OSTR1 0x120
|
||||||
|
#define OSTR2 0x140
|
||||||
|
#define OSTR3 0x160
|
||||||
|
#define VERB_GET_PARAM 0xF0000
|
||||||
|
#define VERB_CONNECT_SEL_GET 0xF0100
|
||||||
|
#define VERB_CONNECT_SEL_SET 0x70100
|
||||||
|
#define VERB_GET_CONNECT_LST 0xF0200
|
||||||
|
#define VERB_PROCESS_STATE_GET 0xF0300
|
||||||
|
#define VERB_PROCESS_STATE_SET 0x70300
|
||||||
|
#define VERB_COEFF_IDX_GET 0xD0000
|
||||||
|
#define VERB_COEFF_IDX_SET 0x50000
|
||||||
|
#define VERB_PROCESS_COEFF_GET 0xC0000
|
||||||
|
#define VERB_PROCESS_COEFF_SET 0x40000
|
||||||
|
#define VERB_AMPLIFIER_GAIN_GET 0xB0000
|
||||||
|
#define VERB_AMPLIFIER_GAIN_SET 0x30000
|
||||||
|
#define VERB_STREAM_FMT_GET 0xA0000
|
||||||
|
#define VERB_STREAM_FMT_SET 0x20000
|
||||||
|
#define VERB_DIGIT_CONVERT1_GET 0xF0D00
|
||||||
|
#define VERB_DIGIT_CONVERT1_SET 0x70D00
|
||||||
|
#define VERB_DIGIT_CONVERT2_GET 0xF0D00
|
||||||
|
#define VERB_DIGIT_CONVERT2_SET 0x70E00
|
||||||
|
#define VERB_POWER_STATE_GET 0xF0500
|
||||||
|
#define VERB_POWER_STATE_SET 0x70500
|
||||||
|
#define VERB_CHAN_STREAM_ID_GET 0xF0600
|
||||||
|
#define VERB_CHAN_STREAM_ID_SET 0x70600
|
||||||
|
#define VERB_SDI_SEL_GET 0xF0400
|
||||||
|
#define VERB_SDI_SEL_SET 0x70400
|
||||||
|
#define VERB_PIN_WIDGET_CTL_GET 0xF0700
|
||||||
|
#define VERB_PIN_WIDGET_CTL_SET 0x70700
|
||||||
|
#define VERB_UNSOL_ENABLE_GET 0xF0800
|
||||||
|
#define VERB_UNSOL_ENABLE_SET 0x70800
|
||||||
|
#define VERB_PIN_SENSE_GET 0xF0900
|
||||||
|
#define VERB_PIN_SENSE_SET 0x70900
|
||||||
|
#define VERB_EAPDBTL_ENABLE_GET 0xF0C00
|
||||||
|
#define VERB_EAPDBTL_ENABLE_SET 0x70C00
|
||||||
|
#define VERB_BEEP_CTL_GET 0xF0A00
|
||||||
|
#define VERB_BEEP_CTL_SET 0x70A00
|
||||||
|
#define VERB_GPI_CTRL0_GET 0xF1000
|
||||||
|
#define VERB_GPI_CTRL0_SET 0x71000
|
||||||
|
#define VERB_GPI_CTRL1_GET 0xF1100
|
||||||
|
#define VERB_GPI_CTRL1_SET 0x71100
|
||||||
|
#define VERB_GPI_CTRL2_GET 0xF1200
|
||||||
|
#define VERB_GPI_CTRL2_SET 0x71200
|
||||||
|
#define VERB_GPI_CTRL3_GET 0xF1300
|
||||||
|
#define VERB_GPI_CTRL3_SET 0x71300
|
||||||
|
#define VERB_GPI_CTRL4_GET 0xF1400
|
||||||
|
#define VERB_GPI_CTRL4_SET 0x71400
|
||||||
|
#define VERB_GPI_CTRL5_GET 0xF1500
|
||||||
|
#define VERB_GPI_CTRL5_SET 0x71500
|
||||||
|
#define VERB_GPI_CTRL6_GET 0xF1600
|
||||||
|
#define VERB_GPI_CTRL6_SET 0x71600
|
||||||
|
#define VERB_GPI_CTRL7_GET 0xF1700
|
||||||
|
#define VERB_GPI_CTRL7_SET 0x71700
|
||||||
|
#define VERB_GPI_CTRL8_GET 0xF1800
|
||||||
|
#define VERB_GPI_CTRL8_SET 0x71800
|
||||||
|
#define VERB_GPI_CTRL9_GET 0xF1900
|
||||||
|
#define VERB_GPI_CTRL9_SET 0x71900
|
||||||
|
#define VERB_GPI_CTRLA_GET 0xF1A00
|
||||||
|
#define VERB_GPI_CTRLA_SET 0x71A00
|
||||||
|
#define VERB_VOL_CTL_GET 0xF0F00
|
||||||
|
#define VERB_VOL_CTL_SET 0x70F00
|
||||||
|
#define VERB_SUB_SYS_ID0_GET 0xF2000
|
||||||
|
#define VERB_SUB_SYS_ID0_SET 0x72000
|
||||||
|
#define VERB_SUB_SYS_ID1_GET 0xF2000
|
||||||
|
#define VERB_SUB_SYS_ID1_SET 0x72100
|
||||||
|
#define VERB_SUB_SYS_ID2_GET 0xF2000
|
||||||
|
#define VERB_SUB_SYS_ID2_SET 0x72200
|
||||||
|
#define VERB_SUB_SYS_ID3_GET 0xF2000
|
||||||
|
#define VERB_SUB_SYS_ID3_SET 0x72300
|
||||||
|
#define VERB_CFG_DFT0_GET 0xF1C00
|
||||||
|
#define VERB_CFG_DFT0_SET 0x71C00
|
||||||
|
#define VERB_CFG_DFT1_GET 0xF1C00
|
||||||
|
#define VERB_CFG_DFT1_SET 0x71D00
|
||||||
|
#define VERB_CFG_DFT2_GET 0xF1C00
|
||||||
|
#define VERB_CFG_DFT2_SET 0x71E00
|
||||||
|
#define VERB_CFG_DFT3_GET 0xF1C00
|
||||||
|
#define VERB_CFG_DFT3_SET 0x71F00
|
||||||
|
#define VERB_STRIPE_CTL_GET 0xF2400
|
||||||
|
#define VERB_STRIPE_CTL_SET 0x72400
|
||||||
|
#define VERB_RST 0x7FF00
|
||||||
|
|
||||||
|
//Parameters
|
||||||
|
#define P_VENDOR_ID 0x00
|
||||||
|
#define P_REVISION_ID 0x02
|
||||||
|
#define P_SUBNODE_CNT 0x04
|
||||||
|
#define P_FUN_GRP_TYPE 0x05
|
||||||
|
#define P_AUDIO_FUN_CAP 0x08
|
||||||
|
#define P_AUDIO_WIDGET_CAP 0x09
|
||||||
|
#define P_SAMPLE_SIZE_RATE_CAP 0x0A
|
||||||
|
#define P_STREAM_FMTS 0x0B
|
||||||
|
#define P_PIN_CAP 0x0C
|
||||||
|
#define P_INPUT_AMP_CAP 0x0D
|
||||||
|
#define P_OUTPUT_AMP_CAP 0x12
|
||||||
|
#define P_CONNECT_LST_LEN 0x0E
|
||||||
|
#define P_POWER_STATES 0x0F
|
||||||
|
#define P_PROCESSING_CAP 0x10
|
||||||
|
#define P_GPIO_CNT 0x11
|
||||||
|
#define P_VOL_KNOB_CAP 0x13
|
||||||
|
|
||||||
|
//Function Group Types
|
||||||
|
//00 reserved
|
||||||
|
#define FGT_AUDIO 1
|
||||||
|
#define FGT_VENDOR_MODEM 2
|
||||||
|
//03-7F reserved
|
||||||
|
//80-FF vendor function group
|
||||||
|
|
||||||
|
//Audio Widget Types
|
||||||
|
#define AWT_OUTPUT 0x0
|
||||||
|
#define AWT_INPUT 0x1
|
||||||
|
#define AWT_MIXER 0x2
|
||||||
|
#define AWT_SELECTOR 0x3
|
||||||
|
#define AWT_PIN_COMPLEX 0x4
|
||||||
|
#define AWT_POWER_WIDGET 0x5
|
||||||
|
#define AWT_VOL_KNOB_WIDGET 0x6
|
||||||
|
#define AWT_BEEP_GEN_WIDGET 0x7
|
||||||
|
#define AWT_VENDOR 0xF
|
||||||
|
#define AWT_NODE 0x10
|
||||||
|
DefineListLoad("ST_AUDIO_WIDGET_TYPES",
|
||||||
|
"Output\0Input\0Mixer\0Sellector\0Pin Complex\0"
|
||||||
|
"Power Widget\0Vol Knob\0Beep Gen\0\0\0\0\0\0\0\0Vendor\0Node\0");
|
||||||
|
|
||||||
|
class CHDBufDesc
|
||||||
|
{
|
||||||
|
I32 * buf;
|
||||||
|
U32 len;
|
||||||
|
U32 ctrl;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define HD_TONES 8
|
||||||
|
|
||||||
|
class CHDAudioCtrl
|
||||||
|
{
|
||||||
|
U8 * bar;
|
||||||
|
CBlkPool * bp;
|
||||||
|
CHeapCtrl * hc;
|
||||||
|
I64 cad;
|
||||||
|
U32 * corb;
|
||||||
|
I64 * rirb;
|
||||||
|
CHDBufDesc *ostr0_bdl, *istr0_bdl;
|
||||||
|
SND_OUT_CONTAINER *ostr0_buf[2], *o_tmp_buf;
|
||||||
|
SND_IN_CONTAINER *istr0_buf[2];
|
||||||
|
CTask * task;
|
||||||
|
I64 waveform;
|
||||||
|
F64 freq, amp;
|
||||||
|
CSndWaveCtrl *tone_swcs[HD_TONES];
|
||||||
|
U8 rirb_rp, corb_wp;
|
||||||
|
Bool audio_task_started, in_running, out_running;
|
||||||
|
}
|
||||||
|
|
||||||
|
hda;
|
||||||
|
MemSet(&hda, 0, sizeof(CHDAudioCtrl));
|
||||||
|
|
||||||
|
U0 HDSyncCORB()
|
||||||
|
{
|
||||||
|
U16 *wp, *rp;
|
||||||
|
wp = hda.bar + HD_CORBWP;
|
||||||
|
*wp = hda.corb_wp;
|
||||||
|
rp = hda.bar + HD_CORBRP;
|
||||||
|
while (*rp &255 != hda.corb_wp)
|
||||||
|
Yield;
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 HDWriteCORB(I64 cad, I64 nid, U32 val)
|
||||||
|
{
|
||||||
|
val |= cad << 28 + nid << 20;
|
||||||
|
hda.corb[++hda.corb_wp] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
I64 HDSyncRIRB()
|
||||||
|
{
|
||||||
|
U16 * _w;
|
||||||
|
I64 wp, res = 0;
|
||||||
|
_w = hda.bar + HD_RIRBWP;
|
||||||
|
wp = *_w;
|
||||||
|
while (hda.rirb_rp != wp)
|
||||||
|
res = hda.rirb[++hda.rirb_rp];
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
I64 HDReadRIRB()
|
||||||
|
{
|
||||||
|
U16 * _w;
|
||||||
|
I64 wp, res = 0;
|
||||||
|
_w = hda.bar + HD_RIRBWP;
|
||||||
|
do {
|
||||||
|
Yield;
|
||||||
|
wp = *_w;
|
||||||
|
} while (wp == hda.rirb_rp);
|
||||||
|
res = hda.rirb[++hda.rirb_rp];
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
I64 HDWriteCORBSync(I64 cad, I64 nid, U32 val)
|
||||||
|
{
|
||||||
|
HDSyncCORB;
|
||||||
|
HDSyncRIRB;
|
||||||
|
HDWriteCORB(cad, nid, val);
|
||||||
|
HDSyncCORB;
|
||||||
|
return HDReadRIRB;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool HDTestCORBSync(I64 cad, I64 nid, U32 val)
|
||||||
|
{
|
||||||
|
//Checks for a response
|
||||||
|
U16 * _w;
|
||||||
|
I64 wp;
|
||||||
|
|
||||||
|
HDSyncCORB;
|
||||||
|
HDSyncRIRB;
|
||||||
|
HDWriteCORB(cad, nid, val);
|
||||||
|
HDSyncCORB;
|
||||||
|
|
||||||
|
Sleep(1);
|
||||||
|
_w = hda.bar + HD_RIRBWP;
|
||||||
|
wp = *_w;
|
||||||
|
if (wp == hda.rirb_rp)
|
||||||
|
return FALSE;
|
||||||
|
HDReadRIRB;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 HDTraverse(I64 cad, I64 nid)
|
||||||
|
{
|
||||||
|
I64 i, len, aud_cap, type;
|
||||||
|
HDWriteCORBSync(cad, nid, VERB_POWER_STATE_SET + 0x00); //0 is on
|
||||||
|
HDWriteCORBSync(cad, nid, VERB_EAPDBTL_ENABLE_SET + 0x02);
|
||||||
|
HDWriteCORBSync(cad, nid, VERB_PROCESS_STATE_SET + 0x02);
|
||||||
|
HDWriteCORBSync(cad, nid, VERB_CONNECT_SEL_SET + 0x00);
|
||||||
|
aud_cap = HDWriteCORBSync(cad, nid, VERB_GET_PARAM + P_SUBNODE_CNT);
|
||||||
|
if (aud_cap.u16[0])
|
||||||
|
{
|
||||||
|
for (i = aud_cap.u16[1]; i < aud_cap.u16[1] + aud_cap.u16[0]; i++)
|
||||||
|
HDTraverse(cad, i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aud_cap = HDWriteCORBSync(cad, nid, VERB_GET_PARAM + P_AUDIO_WIDGET_CAP);
|
||||||
|
type = aud_cap >> 20 &15;
|
||||||
|
if (Bt(&aud_cap, 8))
|
||||||
|
len = HDWriteCORBSync(cad, nid, VERB_GET_PARAM + P_CONNECT_LST_LEN) &127;
|
||||||
|
else
|
||||||
|
len = 0;
|
||||||
|
HDWriteCORBSync(cad, nid, VERB_AMPLIFIER_GAIN_SET + 0xF07F); //set I/O amp #0
|
||||||
|
for (i = 1; i < len; i++)
|
||||||
|
//Set IN amps to mute
|
||||||
|
HDWriteCORBSync(cad, nid, VERB_AMPLIFIER_GAIN_SET + 0x7080 + i << 8);
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case AWT_OUTPUT:
|
||||||
|
if (FALSE) //if disabled
|
||||||
|
HDWriteCORBSync(cad, nid, VERB_CHAN_STREAM_ID_SET + 0x00);
|
||||||
|
else
|
||||||
|
HDWriteCORBSync(cad, nid, VERB_CHAN_STREAM_ID_SET + 0x10);
|
||||||
|
HDWriteCORBSync(cad, nid, VERB_STREAM_FMT_SET + HD_DFT_OUT_FMT);
|
||||||
|
HDWriteCORBSync(cad, nid, VERB_PROCESS_STATE_SET + 0x01);
|
||||||
|
break;
|
||||||
|
case AWT_INPUT:
|
||||||
|
if (TRUE) //if disabled
|
||||||
|
HDWriteCORBSync(cad, nid, VERB_CHAN_STREAM_ID_SET + 0x00);
|
||||||
|
else
|
||||||
|
HDWriteCORBSync(cad, nid, VERB_CHAN_STREAM_ID_SET + 0x20);
|
||||||
|
HDWriteCORBSync(cad, nid, VERB_STREAM_FMT_SET + HD_DFT_IN_FMT);
|
||||||
|
HDWriteCORBSync(cad, nid, VERB_PROCESS_STATE_SET + 0x01);
|
||||||
|
break;
|
||||||
|
case AWT_PIN_COMPLEX:
|
||||||
|
HDWriteCORBSync(cad, nid, VERB_PIN_WIDGET_CTL_SET + 0xE2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 HDRun(Bool in, Bool out)
|
||||||
|
{
|
||||||
|
U32 * _d;
|
||||||
|
if (hda.bar)
|
||||||
|
{
|
||||||
|
if (out)
|
||||||
|
{
|
||||||
|
_d = hda.bar + OSTR0 + STRCTL;
|
||||||
|
*_d = 0x100002;
|
||||||
|
hda.out_running = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in)
|
||||||
|
{
|
||||||
|
_d = hda.bar + ISTR0 + STRCTL;
|
||||||
|
*_d = 0x200002;
|
||||||
|
hda.in_running = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 HDStop(Bool in, Bool out)
|
||||||
|
{
|
||||||
|
U32 * _d;
|
||||||
|
if (hda.bar)
|
||||||
|
{
|
||||||
|
if (out)
|
||||||
|
{
|
||||||
|
_d = hda.bar + OSTR0 + STRCTL;
|
||||||
|
*_d = 0;
|
||||||
|
hda.out_running = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in)
|
||||||
|
{
|
||||||
|
_d = hda.bar + ISTR0 + STRCTL;
|
||||||
|
*_d = 0;
|
||||||
|
hda.in_running = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 HDSnd(F64 freq, I64 waveform = WF_SQUARE, F64 amp = 1.0)
|
||||||
|
{
|
||||||
|
hda.waveform = waveform;
|
||||||
|
hda.amp = amp;
|
||||||
|
hda.freq = freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 HDFillBuf(SND_OUT_CONTAINER *buf, I64)
|
||||||
|
{
|
||||||
|
I64 i, size = SND_BUF_LEN* sizeof(SND_OUT_CONTAINER);
|
||||||
|
if (!hda.o_tmp_buf)
|
||||||
|
hda.o_tmp_buf = SysMAlloc(size);
|
||||||
|
MemSet(hda.o_tmp_buf, 0, size);
|
||||||
|
for (i = 0; i < HD_TONES; i++)
|
||||||
|
SndWaveAddBuf(hda.tone_swcs[i], hda.o_tmp_buf,
|
||||||
|
SND_BUF_LEN / SND_OCHANNELS, hda.freq,
|
||||||
|
hda.waveform, snd_vol *hda.amp);
|
||||||
|
MemCopy(buf, hda.o_tmp_buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 HDAudioTaskEndCB()
|
||||||
|
{
|
||||||
|
I64 i;
|
||||||
|
HDStop(FALSE, TRUE);
|
||||||
|
fp_snd = NULL;
|
||||||
|
for (i = 0; i < HD_TONES; i++)
|
||||||
|
{
|
||||||
|
SndWaveCtrlDel(hda.tone_swcs[i]);
|
||||||
|
hda.tone_swcs[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public U0 HDTonesInit()
|
||||||
|
{
|
||||||
|
I64 i;
|
||||||
|
if (hda.bar)
|
||||||
|
{
|
||||||
|
for (i = 0; i < HD_TONES; i++)
|
||||||
|
{
|
||||||
|
hda.tone_swcs[i]->freq_multiplier = 1.0;
|
||||||
|
hda.tone_swcs[i]->amp_multiplier = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hda.tone_swcs[0]->amp_multiplier = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 HDAudioTask(I64)
|
||||||
|
{
|
||||||
|
//I didn't feel like messing around with PCI interrupts
|
||||||
|
//so this task polls every millisecond to know when to
|
||||||
|
//switch buffers.
|
||||||
|
I64 i, next_obuf_trigger = SND_BUF_LEN* sizeof(SND_OUT_CONTAINER) / 2,
|
||||||
|
obuf_rollover = 0,
|
||||||
|
next_ibuf_trigger = SND_BUF_LEN* sizeof(SND_IN_CONTAINER),
|
||||||
|
ibuf_rollover = 0;
|
||||||
|
U32 *pos_in_obuf = hda.bar + OSTR0 + STRLPIB,
|
||||||
|
*pos_in_ibuf = hda.bar + ISTR0 + STRLPIB;
|
||||||
|
Fs->task_end_cb = &HDAudioTaskEndCB;
|
||||||
|
for (i = 0; i < HD_TONES; i++)
|
||||||
|
hda.tone_swcs[i] = SndWaveCtrlNew;
|
||||||
|
HDTonesInit;
|
||||||
|
hda.freq = 0;
|
||||||
|
Sound;
|
||||||
|
fp_snd = &HDSnd;
|
||||||
|
fp_snd_fill_buf = &HDFillBuf;
|
||||||
|
fp_snd_copy_buf = NULL;
|
||||||
|
snd_obuf_num = 1;
|
||||||
|
snd_ibuf_num = 1;
|
||||||
|
HDRun(FALSE, TRUE);
|
||||||
|
hda.audio_task_started = TRUE; //This flag is probably not necessary
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
if (next_obuf_trigger - obuf_rollover <= *pos_in_obuf< next_obuf_trigger - obuf_rollover +
|
||||||
|
(HD_POS_BUF_MULTIPLES - 1) *SND_BUF_LEN* sizeof(SND_OUT_CONTAINER))
|
||||||
|
{
|
||||||
|
next_obuf_trigger += SND_BUF_LEN* sizeof(SND_OUT_CONTAINER);
|
||||||
|
if (next_obuf_trigger - obuf_rollover >=
|
||||||
|
HD_POS_BUF_MULTIPLES *SND_BUF_LEN* sizeof(SND_OUT_CONTAINER))
|
||||||
|
obuf_rollover += HD_POS_BUF_MULTIPLES *SND_BUF_LEN *
|
||||||
|
sizeof(SND_OUT_CONTAINER);
|
||||||
|
if (fp_snd_fill_buf)
|
||||||
|
{
|
||||||
|
LBts(&snd_flags, Sf_FILLING_OUT);
|
||||||
|
(*fp_snd_fill_buf)(hda.ostr0_buf[snd_obuf_num & 1], snd_obuf_num);
|
||||||
|
if (IsMute)
|
||||||
|
MemSet(hda.ostr0_buf[snd_obuf_num & 1], 0,
|
||||||
|
SND_BUF_LEN* sizeof(SND_OUT_CONTAINER));
|
||||||
|
LBtr(&snd_flags, Sf_FILLING_OUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
snd_obuf_num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_ibuf_trigger - ibuf_rollover <= *pos_in_ibuf< next_ibuf_trigger - ibuf_rollover + (HD_POS_BUF_MULTIPLES - 1) *
|
||||||
|
SND_BUF_LEN* sizeof(SND_IN_CONTAINER))
|
||||||
|
{
|
||||||
|
next_ibuf_trigger += SND_BUF_LEN* sizeof(SND_IN_CONTAINER);
|
||||||
|
if (next_ibuf_trigger - ibuf_rollover >=
|
||||||
|
HD_POS_BUF_MULTIPLES *SND_BUF_LEN* sizeof(SND_IN_CONTAINER))
|
||||||
|
ibuf_rollover += HD_POS_BUF_MULTIPLES *SND_BUF_LEN *
|
||||||
|
sizeof(SND_IN_CONTAINER);
|
||||||
|
if (fp_snd_copy_buf)
|
||||||
|
(*fp_snd_copy_buf)(hda.istr0_buf[snd_obuf_num & 1], snd_ibuf_num);
|
||||||
|
snd_ibuf_num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Sleep(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 HDRst()
|
||||||
|
{
|
||||||
|
U32 d, *_d;
|
||||||
|
HDStop(TRUE, TRUE);
|
||||||
|
_d = hda.bar + HD_GCTL;
|
||||||
|
*_d = 0; //rst
|
||||||
|
do {
|
||||||
|
Sleep(1);
|
||||||
|
d = *_d;
|
||||||
|
} while (d & 1);
|
||||||
|
*_d = 1;
|
||||||
|
do {
|
||||||
|
Sleep(1);
|
||||||
|
d = *_d;
|
||||||
|
} while (!(d & 1));
|
||||||
|
Sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public U0 HDAudioEnd(Bool rst = TRUE)
|
||||||
|
{
|
||||||
|
snd_dev = SD_PC_SPEAKER;
|
||||||
|
if (hda.bar)
|
||||||
|
{
|
||||||
|
Kill(hda.task);
|
||||||
|
hda.task = NULL;
|
||||||
|
if (rst)
|
||||||
|
HDRst;
|
||||||
|
Free(hda.corb);
|
||||||
|
Free(hda.rirb);
|
||||||
|
Free(hda.o_tmp_buf);
|
||||||
|
Free(hda.ostr0_buf[0]);
|
||||||
|
Free(hda.ostr0_buf[1]);
|
||||||
|
Free(hda.istr0_buf[0]);
|
||||||
|
Free(hda.istr0_buf[1]);
|
||||||
|
Free(hda.ostr0_bdl);
|
||||||
|
Free(hda.istr0_bdl);
|
||||||
|
Mem32DevFree(hda.bar);
|
||||||
|
hda.bar = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 HDAudioUncachedInit()
|
||||||
|
{
|
||||||
|
I64 shared_blks = 1;
|
||||||
|
hda.bp = Mem2MegUncachedAlloc(&shared_blks);
|
||||||
|
hda.hc = HeapCtrlBPInit(hda.bp, shared_blks << 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bool HDAudioInit(I64 hd_bus, I64 hd_dev, I64 hd_fun)
|
||||||
|
{
|
||||||
|
I64 i;
|
||||||
|
U32 * _d;
|
||||||
|
U16 w, *_w;
|
||||||
|
U8 * _b;
|
||||||
|
if (hda.bar)
|
||||||
|
HDAudioEnd;
|
||||||
|
else
|
||||||
|
HDAudioUncachedInit;
|
||||||
|
if (PCIReadU16(hd_bus, hd_dev, hd_fun, 0) == 0x8086 &&
|
||||||
|
(hda.bar = PCIReadU32(hd_bus, hd_dev, hd_fun, 0x10) &~(0x1F)))
|
||||||
|
{
|
||||||
|
PCIWriteU16(hd_bus, hd_dev, hd_fun, 0x04,
|
||||||
|
PCIReadU16(hd_bus, hd_dev, hd_fun, 0x04) | 0x406);
|
||||||
|
|
||||||
|
HDRst;
|
||||||
|
|
||||||
|
hda.corb = CAllocAligned(HD_CORB_ENTRIES* sizeof(U32), 128, hda.hc);
|
||||||
|
_d = hda.bar + HD_CORBLBASE;
|
||||||
|
*_d = hda.corb(I64).u32[0];
|
||||||
|
_d = hda.bar + HD_CORBUBASE;
|
||||||
|
*_d = hda.corb(I64).u32[1];
|
||||||
|
|
||||||
|
hda.rirb = CAllocAligned(HD_RIRB_ENTRIES* sizeof(I64), 128, hda.hc);
|
||||||
|
_d = hda.bar + HD_RIRBLBASE;
|
||||||
|
*_d = hda.rirb(I64).u32[0];
|
||||||
|
_d = hda.bar + HD_RIRBUBASE;
|
||||||
|
*_d = hda.rirb(I64).u32[1];
|
||||||
|
|
||||||
|
_w = hda.bar + HD_CORBRP;
|
||||||
|
*_w = 0x8000; //Rst read ptr
|
||||||
|
do { Yield;
|
||||||
|
w = *_w;
|
||||||
|
} while (!(w & 0x8000));
|
||||||
|
*_w = 0x0000; //Rst read ptr
|
||||||
|
do { Yield;
|
||||||
|
w = *_w;
|
||||||
|
} while (w & 0x8000);
|
||||||
|
|
||||||
|
_w = hda.bar + HD_RIRBWP;
|
||||||
|
*_w = 0x8000; //Rst write ptr
|
||||||
|
|
||||||
|
_b = hda.bar + HD_CORBCTL;
|
||||||
|
*_b = 0x02; //Run
|
||||||
|
_b = hda.bar + HD_RIRBCTL;
|
||||||
|
*_b = 0x02; //Run
|
||||||
|
|
||||||
|
_w = hda.bar + HD_CORBWP;
|
||||||
|
hda.corb_wp = *_w;
|
||||||
|
_w = hda.bar + HD_RIRBWP;
|
||||||
|
hda.rirb_rp = *_w;
|
||||||
|
|
||||||
|
hda.ostr0_bdl = CAllocAligned( HD_BDL_ENTRIES* sizeof(CHDBufDesc), 128, hda.hc);
|
||||||
|
_d = hda.bar + OSTR0 + STRBDPL;
|
||||||
|
*_d = hda.ostr0_bdl(I64).u32[0];
|
||||||
|
_d = hda.bar + OSTR0 + STRBDPU;
|
||||||
|
*_d = hda.ostr0_bdl(I64).u32[1];
|
||||||
|
for (i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
hda.ostr0_bdl[i].buf = hda.ostr0_buf[i] =
|
||||||
|
CAllocAligned( SND_BUF_LEN* sizeof(SND_OUT_CONTAINER), 128, hda.hc);
|
||||||
|
hda.ostr0_bdl[i].len = SND_BUF_LEN* sizeof(SND_OUT_CONTAINER);
|
||||||
|
hda.ostr0_bdl[i].ctrl = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hda.istr0_bdl = CAllocAligned( HD_BDL_ENTRIES* sizeof(CHDBufDesc), 128, hda.hc);
|
||||||
|
_d = hda.bar + ISTR0 + STRBDPL;
|
||||||
|
*_d = hda.istr0_bdl(I64).u32[0];
|
||||||
|
_d = hda.bar + ISTR0 + STRBDPU;
|
||||||
|
*_d = hda.istr0_bdl(I64).u32[1];
|
||||||
|
for (i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
hda.istr0_bdl[i].buf = hda.istr0_buf[i] = CAllocAligned( SND_BUF_LEN* sizeof(SND_IN_CONTAINER), 128, hda.hc);
|
||||||
|
hda.istr0_bdl[i].len = SND_BUF_LEN* sizeof(SND_IN_CONTAINER);
|
||||||
|
hda.istr0_bdl[i].ctrl = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_w = hda.bar + HD_STATESTS;
|
||||||
|
w = *_w;
|
||||||
|
while (w)
|
||||||
|
{
|
||||||
|
hda.cad = Bsf(w);
|
||||||
|
if (HDTestCORBSync(hda.cad, 0, VERB_GET_PARAM + P_SUBNODE_CNT))
|
||||||
|
{
|
||||||
|
HDTraverse(hda.cad, 0);
|
||||||
|
|
||||||
|
_d = hda.bar + OSTR0 + STRLPIB;
|
||||||
|
*_d = 0;
|
||||||
|
_d = hda.bar + OSTR0 + STRCBL;
|
||||||
|
*_d = HD_POS_BUF_MULTIPLES *SND_BUF_LEN* sizeof(SND_OUT_CONTAINER);
|
||||||
|
_w = hda.bar + OSTR0 + STRLVI;
|
||||||
|
*_w = 1; //last valid idx
|
||||||
|
_w = hda.bar + OSTR0 + STRFMT;
|
||||||
|
*_w = HD_DFT_OUT_FMT;
|
||||||
|
|
||||||
|
_d = hda.bar + ISTR0 + STRLPIB;
|
||||||
|
*_d = 0;
|
||||||
|
_d = hda.bar + ISTR0 + STRCBL;
|
||||||
|
*_d = HD_POS_BUF_MULTIPLES *SND_BUF_LEN* sizeof(SND_IN_CONTAINER);
|
||||||
|
_w = hda.bar + ISTR0 + STRLVI;
|
||||||
|
*_w = 1; //last valid idx
|
||||||
|
_w = hda.bar + ISTR0 + STRFMT;
|
||||||
|
*_w = HD_DFT_IN_FMT;
|
||||||
|
|
||||||
|
LBts(&sys_semas[SEMA_SOUND], 0); //turn off until cfg completed
|
||||||
|
LBtr(&snd_flags, Sf_FILLING_OUT);
|
||||||
|
hda.audio_task_started = FALSE;
|
||||||
|
if (mp_count > 1)
|
||||||
|
hda.task = Spawn(&HDAudioTask, NULL, "HD Audio", 3);
|
||||||
|
else
|
||||||
|
hda.task = Spawn(&HDAudioTask, NULL, "HD Audio");
|
||||||
|
while (!hda.audio_task_started)
|
||||||
|
Yield;
|
||||||
|
snd_dev = SD_HD_AUDIO;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Btr(&w, hda.cad);
|
||||||
|
}
|
||||||
|
|
||||||
|
HDAudioEnd(FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
hda.bar = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool HDAudioScan()
|
||||||
|
{
|
||||||
|
I64 i = -1, j;
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
j = PCIClassFind(0x040300, ++i);
|
||||||
|
if (j < 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (HDAudioInit(j.u8[2], j.u8[1], j.u8[0]))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HDAudioScan;
|
||||||
|
|
||||||
|
#
|
||||||
|
help_index ""
|
720
src/Home/Sound/HDAudio1/Sup1HDAudio/HDCfg.ZC
Normal file
720
src/Home/Sound/HDAudio1/Sup1HDAudio/HDCfg.ZC
Normal file
|
@ -0,0 +1,720 @@
|
||||||
|
|
||||||
|
#define CONNECTS_NUM 16
|
||||||
|
|
||||||
|
class MyMass: CMass
|
||||||
|
{
|
||||||
|
F64 radius;
|
||||||
|
U8 nid, type, num_connects, cur_connect;
|
||||||
|
U32 audio_widget_capabilities;
|
||||||
|
U8 connect_lst[CONNECTS_NUM];
|
||||||
|
U8 gain_lst[CONNECTS_NUM];
|
||||||
|
U32 pin_capabilities, pin_sense,
|
||||||
|
pcm_size_rates,
|
||||||
|
in_amp_cap, out_amp_cap;
|
||||||
|
U8 pin_widget_ctl;
|
||||||
|
Bool disabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MySpring: CSpring
|
||||||
|
{
|
||||||
|
I64 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
CMathODE *ode = NULL;
|
||||||
|
|
||||||
|
#define BORDER 10
|
||||||
|
|
||||||
|
U0 DrawIt(CTask *task, CDC *dc)
|
||||||
|
{
|
||||||
|
Bool old_suspend;
|
||||||
|
I16 * buf;
|
||||||
|
I64 i, cxx, cyy,
|
||||||
|
cy = task->pix_height >> 1;
|
||||||
|
F64 dx, dy, d;
|
||||||
|
MyMass * tmpm;
|
||||||
|
MySpring * tmps;
|
||||||
|
|
||||||
|
old_suspend = Suspend(task);
|
||||||
|
tmps = ode->next_spring;
|
||||||
|
while (tmps != &ode->next_spring)
|
||||||
|
{
|
||||||
|
dc->color = tmps->color;
|
||||||
|
GrLine(dc, tmps->end1->x, tmps->end1->y,
|
||||||
|
tmps->end2->x, tmps->end2->y);
|
||||||
|
cxx = (tmps->end1->x + tmps->end2->x) / 2;
|
||||||
|
cyy = (tmps->end1->y + tmps->end2->y) / 2;
|
||||||
|
dx = tmps->end1->x - tmps->end2->x;
|
||||||
|
dy = tmps->end1->y - tmps->end2->y;
|
||||||
|
d = Sqrt(dx *dx + dy *dy);
|
||||||
|
dx /= d;
|
||||||
|
dy /= d;
|
||||||
|
GrLine(dc, cxx, cyy, cxx + 3.0 *dy - 3.0 *dx, cyy - 3.0 *dx - 3.0 *dy);
|
||||||
|
GrLine(dc, cxx, cyy, cxx - 3.0 *dy - 3.0 *dx, cyy + 3.0 *dx - 3.0 *dy);
|
||||||
|
tmps = tmps->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpm = ode->next_mass;
|
||||||
|
while (tmpm != &ode->next_mass)
|
||||||
|
{
|
||||||
|
if (tmpm->disabled)
|
||||||
|
dc->color = BLUE;
|
||||||
|
else
|
||||||
|
dc->color = LTBLUE;
|
||||||
|
GrCircle(dc, tmpm->x, tmpm->y, tmpm->radius);
|
||||||
|
GrPrint(dc, tmpm->x, tmpm->y - FONT_HEIGHT / 2, "%02X%3tZ",
|
||||||
|
tmpm->nid, tmpm->type,
|
||||||
|
"ST_AUDIO_WIDGET_TYPES");
|
||||||
|
tmpm = tmpm->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
Suspend(task, old_suspend);
|
||||||
|
dc->color = BLUE;
|
||||||
|
buf = hda.istr0_buf[0];
|
||||||
|
for (i = 0; i < SND_BUF_LEN; i++)
|
||||||
|
GrPlot(dc, i *task->pix_width / SND_BUF_LEN,
|
||||||
|
cy - buf[i] *cy / I16_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 MyDerivative(CMathODE *ode, F64, COrder2D3 *, COrder2D3 *)
|
||||||
|
{
|
||||||
|
//The forces due to springs and drag are
|
||||||
|
//automatically handled by the
|
||||||
|
//ode code.We can add new forces
|
||||||
|
//here.
|
||||||
|
CTask *task = ode->win_task;
|
||||||
|
I64 h = task->pix_width, v = task->pix_height;
|
||||||
|
F64 d, dd;
|
||||||
|
CD3 p;
|
||||||
|
MyMass *tmpm1, *tmpm2;
|
||||||
|
|
||||||
|
tmpm1 = ode->next_mass;
|
||||||
|
while (tmpm1 != &ode->next_mass)
|
||||||
|
{
|
||||||
|
tmpm2 = tmpm1->next;
|
||||||
|
while (tmpm2 != &ode->next_mass)
|
||||||
|
{
|
||||||
|
D3Sub(&p, &tmpm2->state->x, &tmpm1->state->x);
|
||||||
|
dd = D3NormSqr(&p);
|
||||||
|
if (dd <= Sqr(tmpm1->radius + tmpm2->radius))
|
||||||
|
{
|
||||||
|
d = Sqrt(dd) + 0.0001;
|
||||||
|
dd = 10.0* Sqr(Sqr(Sqr(tmpm1->radius + tmpm2->radius) - dd));
|
||||||
|
D3MulEqu(&p, dd / d);
|
||||||
|
D3AddEqu(&tmpm2->DstateDt->DxDt, &p);
|
||||||
|
D3SubEqu(&tmpm1->DstateDt->DxDt, &p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
D3MulEqu(&p, 100000.0 / dd);
|
||||||
|
D3AddEqu(&tmpm2->DstateDt->DxDt, &p);
|
||||||
|
D3SubEqu(&tmpm1->DstateDt->DxDt, &p);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpm2 = tmpm2->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmpm1->state->x < BORDER)
|
||||||
|
tmpm1->DstateDt->DxDt += 1000* Sqr(tmpm1->state->x - BORDER);
|
||||||
|
if (tmpm1->state->y < BORDER)
|
||||||
|
tmpm1->DstateDt->DyDt += 1000* Sqr(tmpm1->state->y - BORDER);
|
||||||
|
if (tmpm1->state->x > h - BORDER - FONT_WIDTH *6)
|
||||||
|
tmpm1->DstateDt->DxDt -= 1000 *
|
||||||
|
Sqr(tmpm1->state->x - (h - BORDER - FONT_WIDTH *6));
|
||||||
|
if (tmpm1->state->y > v - BORDER)
|
||||||
|
tmpm1->DstateDt->DyDt -= 1000* Sqr(tmpm1->state->y - (v - BORDER));
|
||||||
|
tmpm1 = tmpm1->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MyMass* PlaceMass(I64 nid)
|
||||||
|
{
|
||||||
|
MyMass *tmpm = CAlloc(sizeof(MyMass));
|
||||||
|
tmpm->mass = 1.0;
|
||||||
|
tmpm->drag_profile_factor = 100.0;
|
||||||
|
tmpm->radius = 5;
|
||||||
|
tmpm->nid = nid;
|
||||||
|
tmpm->gain_lst[0] = 0x7F;
|
||||||
|
MemSet(tmpm->gain_lst + 1, 0x80, (CONNECTS_NUM - 1) *sizeof(U8));
|
||||||
|
QueueInsert(tmpm, ode->last_mass);
|
||||||
|
return tmpm;
|
||||||
|
}
|
||||||
|
|
||||||
|
MyMass* FindMassByNID(I64 nid)
|
||||||
|
{
|
||||||
|
MyMass * tmpm;
|
||||||
|
tmpm = ode->next_mass;
|
||||||
|
while (tmpm != &ode->next_mass)
|
||||||
|
{
|
||||||
|
if (tmpm->nid == nid)
|
||||||
|
return tmpm;
|
||||||
|
tmpm = tmpm->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
MyMass* FindMassByXY(I64 x, I64 y)
|
||||||
|
{
|
||||||
|
I64 dd, best_dd = I64_MAX;
|
||||||
|
MyMass *tmpm, *res = NULL;
|
||||||
|
tmpm = ode->next_mass;
|
||||||
|
while (tmpm != &ode->next_mass)
|
||||||
|
{
|
||||||
|
dd = SqrI64(tmpm->x - x) + SqrI64(tmpm->y - y);
|
||||||
|
if (dd < best_dd)
|
||||||
|
{
|
||||||
|
res = tmpm;
|
||||||
|
best_dd = dd;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpm = tmpm->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
I64 FindConnectIndex(MyMass *tmpm, I64 nid)
|
||||||
|
{
|
||||||
|
I64 i;
|
||||||
|
for (i = 0; i < tmpm->num_connects; i++)
|
||||||
|
if (tmpm->connect_lst[i] == nid)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
MySpring* PlaceSpring(MyMass *tmpm1, MyMass *tmpm2)
|
||||||
|
{
|
||||||
|
MySpring *tmps = CAlloc(sizeof(MySpring));
|
||||||
|
tmps->end1 = tmpm1;
|
||||||
|
tmps->end2 = tmpm2;
|
||||||
|
tmps->const = 10;
|
||||||
|
tmps->rest_len = 0;
|
||||||
|
tmps->color = LTGRAY;
|
||||||
|
QueueInsert(tmps, ode->last_spring);
|
||||||
|
return tmps;
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 RedoSprings()
|
||||||
|
{
|
||||||
|
I64 i, k;
|
||||||
|
MyMass *tmpm, *tmpm1;
|
||||||
|
MySpring * tmps;
|
||||||
|
|
||||||
|
QueueDel(&ode->next_spring, TRUE);
|
||||||
|
tmpm = ode->next_mass;
|
||||||
|
while (tmpm != &ode->next_mass)
|
||||||
|
{
|
||||||
|
for (i = 0; i < tmpm->num_connects; i++)
|
||||||
|
{
|
||||||
|
if ((k = tmpm->connect_lst[i]) &&
|
||||||
|
(tmpm1 = FindMassByNID(k)))
|
||||||
|
{
|
||||||
|
tmps = PlaceSpring(tmpm, tmpm1);
|
||||||
|
switch (tmpm->type)
|
||||||
|
{
|
||||||
|
case AWT_MIXER:
|
||||||
|
if (!(tmpm->gain_lst[i] &0x80))
|
||||||
|
{
|
||||||
|
//If not mute
|
||||||
|
tmps->color = GREEN;
|
||||||
|
tmps->const = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case AWT_INPUT:
|
||||||
|
case AWT_SELECTOR:
|
||||||
|
case AWT_PIN_COMPLEX:
|
||||||
|
case AWT_VENDOR:
|
||||||
|
if (i == tmpm->cur_connect)
|
||||||
|
{
|
||||||
|
tmps->color = RED;
|
||||||
|
tmps->const = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpm = tmpm->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 Init()
|
||||||
|
{
|
||||||
|
ode = ODENew(0, 1e-4, ODEF_HAS_MASSES);
|
||||||
|
ode->derive = &MyDerivative;
|
||||||
|
ode->drag_v2 = 0.002;
|
||||||
|
ode->drag_v3 = 0.00001;
|
||||||
|
ode->acceleration_limit = 5e3;
|
||||||
|
|
||||||
|
QueueInsert(ode, Fs->last_ode);
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 CleanUp()
|
||||||
|
{
|
||||||
|
QueueRemove(ode);
|
||||||
|
QueueDel(&ode->next_mass, TRUE);
|
||||||
|
QueueDel(&ode->next_spring, TRUE);
|
||||||
|
ODEDel(ode);
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 HDCfgConnectLst(MyMass *tmpm, I64 cad, I64 nid)
|
||||||
|
{
|
||||||
|
I64 i, j, connection_lst_len;
|
||||||
|
j = HDWriteCORBSync(cad, nid, VERB_GET_PARAM + P_CONNECT_LST_LEN);
|
||||||
|
connection_lst_len = j &127;
|
||||||
|
if (j & 128)
|
||||||
|
{
|
||||||
|
//Long form?
|
||||||
|
for (i = 0; i < connection_lst_len; i += 2)
|
||||||
|
{
|
||||||
|
j = HDWriteCORBSync(cad, nid, VERB_GET_CONNECT_LST + i);
|
||||||
|
tmpm->connect_lst[tmpm->num_connects++] = j.u16[0];
|
||||||
|
if (i + 1 < connection_lst_len)
|
||||||
|
tmpm->connect_lst[tmpm->num_connects++] = j.u16[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = 0; i < connection_lst_len; i += 4)
|
||||||
|
{
|
||||||
|
j = HDWriteCORBSync(cad, nid, VERB_GET_CONNECT_LST + i);
|
||||||
|
tmpm->connect_lst[tmpm->num_connects++] = j.u8[0];
|
||||||
|
if (i + 1 < connection_lst_len)
|
||||||
|
tmpm->connect_lst[tmpm->num_connects++] = j.u8[1];
|
||||||
|
if (i + 2 < connection_lst_len)
|
||||||
|
tmpm->connect_lst[tmpm->num_connects++] = j.u8[2];
|
||||||
|
if (i + 3 < connection_lst_len)
|
||||||
|
tmpm->connect_lst[tmpm->num_connects++] = j.u8[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 HDCfgTraverse(I64 cad, I64 nid)
|
||||||
|
{
|
||||||
|
I64 i, j;
|
||||||
|
MyMass *tmpm = PlaceMass(nid);
|
||||||
|
j = HDWriteCORBSync(cad, nid, VERB_GET_PARAM + P_SUBNODE_CNT);
|
||||||
|
if (j.u16[0])
|
||||||
|
{
|
||||||
|
tmpm->type = AWT_NODE;
|
||||||
|
for (i = j.u16[1]; i < j.u16[1] + j.u16[0]; i++)
|
||||||
|
HDCfgTraverse(cad, i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmpm->audio_widget_capabilities =
|
||||||
|
HDWriteCORBSync(cad, nid, VERB_GET_PARAM + P_AUDIO_WIDGET_CAP);
|
||||||
|
tmpm->pcm_size_rates =
|
||||||
|
HDWriteCORBSync(cad, nid, VERB_GET_PARAM + P_SAMPLE_SIZE_RATE_CAP);
|
||||||
|
tmpm->in_amp_cap = HDWriteCORBSync(cad, nid, VERB_GET_PARAM + P_INPUT_AMP_CAP);
|
||||||
|
tmpm->out_amp_cap = HDWriteCORBSync(cad, nid, VERB_GET_PARAM + P_OUTPUT_AMP_CAP);
|
||||||
|
tmpm->type = tmpm->audio_widget_capabilities >> 20 &15;
|
||||||
|
switch (tmpm->type)
|
||||||
|
{
|
||||||
|
case AWT_PIN_COMPLEX:
|
||||||
|
tmpm->pin_widget_ctl =
|
||||||
|
HDWriteCORBSync(cad, nid, VERB_PIN_WIDGET_CTL_GET);
|
||||||
|
tmpm->pin_capabilities =
|
||||||
|
HDWriteCORBSync(cad, nid, VERB_GET_PARAM + P_PIN_CAP);
|
||||||
|
if (Bt(&tmpm->pin_capabilities, 0) ||
|
||||||
|
Bt(&tmpm->pin_capabilities, 2))
|
||||||
|
tmpm->pin_sense = HDWriteCORBSync(cad, nid, VERB_PIN_SENSE_GET);
|
||||||
|
HDWriteCORBSync(cad, nid, VERB_CONNECT_SEL_SET + 0x00);
|
||||||
|
break;
|
||||||
|
case AWT_INPUT:
|
||||||
|
tmpm->disabled = TRUE;
|
||||||
|
case AWT_SELECTOR:
|
||||||
|
case AWT_VENDOR:
|
||||||
|
HDWriteCORBSync(cad, nid, VERB_CONNECT_SEL_SET + 0x00);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Bt(&tmpm->audio_widget_capabilities, 8))
|
||||||
|
HDCfgConnectLst(tmpm, cad, nid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 HDCfgRandomizeXY()
|
||||||
|
{
|
||||||
|
I64 h = Fs->pix_width, v = Fs->pix_height;
|
||||||
|
MyMass * tmpm;
|
||||||
|
tmpm = ode->next_mass;
|
||||||
|
while (tmpm != &ode->next_mass)
|
||||||
|
{
|
||||||
|
tmpm->x = RandU32 % (h - 2 *BORDER - FONT_WIDTH *6) + BORDER;
|
||||||
|
tmpm->y = RandU32 % (v - 2 *BORDER) + BORDER;
|
||||||
|
tmpm = tmpm->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 HDCfgPopUpInfoTask(MyMass *tmpm)
|
||||||
|
{
|
||||||
|
I64 i;
|
||||||
|
"$$FG,RED$$NID:$$FG$$0x%02X$$FG,RED$$Type:$$FG$$%Z\n",
|
||||||
|
tmpm->nid, tmpm->type, "ST_AUDIO_WIDGET_TYPES";
|
||||||
|
|
||||||
|
i = tmpm->audio_widget_capabilities;
|
||||||
|
"\n$$FG,RED$$Audio Widget Capabilities:$$FG$$\n";
|
||||||
|
if (Bt(&i, 0))
|
||||||
|
"Stereo,";
|
||||||
|
if (Bt(&i, 1))
|
||||||
|
"In Amp,";
|
||||||
|
if (Bt(&i, 2))
|
||||||
|
"Out Amp,";
|
||||||
|
if (Bt(&i, 3))
|
||||||
|
"AmpOverride,";
|
||||||
|
if (Bt(&i, 4))
|
||||||
|
"FmtOverride,";
|
||||||
|
if (Bt(&i, 5))
|
||||||
|
"Stripe,";
|
||||||
|
if (Bt(&i, 6))
|
||||||
|
"Proc Wgt,";
|
||||||
|
if (Bt(&i, 7))
|
||||||
|
"Unsolicited,";
|
||||||
|
if (Bt(&i, 8))
|
||||||
|
"Cnt Lst,";
|
||||||
|
if (Bt(&i, 9))
|
||||||
|
"Digital,";
|
||||||
|
if (Bt(&i, 10))
|
||||||
|
"Power Ctrl,";
|
||||||
|
if (Bt(&i, 11))
|
||||||
|
"Left/Right Swap,";
|
||||||
|
"Delay:%d\n", i.u16[1] &0xF;
|
||||||
|
|
||||||
|
i = tmpm->in_amp_cap;
|
||||||
|
"\n$$FG,RED$$Input Amp Capabilities:$$FG$$\n"
|
||||||
|
"Offset:0x%02X Steps:0x%02X StepSize:%5.2fdB Mutable:%d\n",
|
||||||
|
i &127, i.u8[1] &127 + 1, 0.25 *(i.u16[1] &127), Bt(&i, 31);
|
||||||
|
|
||||||
|
i = tmpm->out_amp_cap;
|
||||||
|
"\n$$FG,RED$$Output Amp Capabilities:$$FG$$\n"
|
||||||
|
"Offset:0x%02X Steps:0x%02X StepSize:%5.2fdB Mutable:%d\n",
|
||||||
|
i &127, i.u8[1] &127 + 1, 0.25 *(i.u16[1] &127), Bt(&i, 31);
|
||||||
|
|
||||||
|
"\n$$FG,RED$$Size Rates Capabilities:$$FG$$\n";
|
||||||
|
for (i = 0; i < 21; i++)
|
||||||
|
if (Bt(&tmpm->pcm_size_rates, i))
|
||||||
|
"%z", i,
|
||||||
|
" 8.0kHz\0 11.025kHz\0 16.0kHz\0 22.05kHz\0"
|
||||||
|
" 32.0kHz\0 44.1kHz\0 48.0kHz\0 88.2kHz\0"
|
||||||
|
" 96.0kHz\0 176.4kHz\0 192.0kHz\0 384kHz\0"
|
||||||
|
"\0\0\0\0"
|
||||||
|
" 8Bit\0 16bit\0 20Bit\0 24Bit\0 32Bit\0";
|
||||||
|
'\n';
|
||||||
|
|
||||||
|
"\n$$FG,RED$$Connection Lst:$$FG$$\n";
|
||||||
|
for (i = 0; i < tmpm->num_connects; i++)
|
||||||
|
"%02X,", tmpm->connect_lst[i];
|
||||||
|
'\n';
|
||||||
|
|
||||||
|
"\n$$FG,RED$$Gain Lst:$$FG$$\n";
|
||||||
|
for (i = 0; i < tmpm->num_connects; i++)
|
||||||
|
"%02X,", tmpm->gain_lst[i];
|
||||||
|
'\n';
|
||||||
|
|
||||||
|
switch (tmpm->type)
|
||||||
|
{
|
||||||
|
case AWT_PIN_COMPLEX:
|
||||||
|
"\n$$FG,RED$$Pin Capabilities:$$FG$$\n";
|
||||||
|
i = tmpm->pin_capabilities;
|
||||||
|
if (Bt(&i, 0))
|
||||||
|
"Impedance Sense,";
|
||||||
|
if (Bt(&i, 1))
|
||||||
|
"Trigger Required,";
|
||||||
|
if (Bt(&i, 2))
|
||||||
|
"Presence Detect,";
|
||||||
|
if (Bt(&i, 3))
|
||||||
|
"Headphone Drive,";
|
||||||
|
if (Bt(&i, 4))
|
||||||
|
"Output,";
|
||||||
|
if (Bt(&i, 5))
|
||||||
|
"Input,";
|
||||||
|
if (Bt(&i, 6))
|
||||||
|
"Balanced,";
|
||||||
|
if (Bt(&i, 16))
|
||||||
|
"EAPD,";
|
||||||
|
"Vref:%02X\n\n", i.u8[1];
|
||||||
|
if (Bt(&tmpm->pin_capabilities, 0) ||
|
||||||
|
Bt(&tmpm->pin_capabilities, 2))
|
||||||
|
tmpm->pin_sense = HDWriteCORBSync(hda.cad,
|
||||||
|
tmpm->nid, VERB_PIN_SENSE_GET);
|
||||||
|
if (Bt(&tmpm->pin_capabilities, 0))
|
||||||
|
"Impedance Measurement:%08X\n", tmpm->pin_sense &0x7FFFFFFF;
|
||||||
|
if (Bt(&tmpm->pin_capabilities, 2))
|
||||||
|
"Presence:%d\n", Bt(&tmpm->pin_sense, 31);
|
||||||
|
"\n\nPin widget ctrl bits:\n"
|
||||||
|
"7: High phn enable (low impedance output amp)\n"
|
||||||
|
"6: Output Enable\n"
|
||||||
|
"5: Input Enable\n"
|
||||||
|
"0-2: Vref 0=HiZ 1=50% 2=Gnd 4=80% 5=100%\n";
|
||||||
|
tmpm->pin_widget_ctl = I64Get("Widget Ctrl (0x%02X):",
|
||||||
|
tmpm->pin_widget_ctl, 0, 0xFF);
|
||||||
|
HDWriteCORBSync(hda.cad, tmpm->nid,
|
||||||
|
VERB_PIN_WIDGET_CTL_SET + tmpm->pin_widget_ctl);
|
||||||
|
break;
|
||||||
|
case AWT_INPUT:
|
||||||
|
"Disable";
|
||||||
|
if (tmpm->disabled = YorN)
|
||||||
|
HDWriteCORBSync(hda.cad, tmpm->nid, VERB_CHAN_STREAM_ID_SET + 0x00);
|
||||||
|
else
|
||||||
|
HDWriteCORBSync(hda.cad, tmpm->nid, VERB_CHAN_STREAM_ID_SET + 0x20);
|
||||||
|
'\n';
|
||||||
|
break;
|
||||||
|
case AWT_OUTPUT:
|
||||||
|
"Disable";
|
||||||
|
if (tmpm->disabled = YorN)
|
||||||
|
HDWriteCORBSync(hda.cad, tmpm->nid, VERB_CHAN_STREAM_ID_SET + 0x00);
|
||||||
|
else
|
||||||
|
HDWriteCORBSync(hda.cad, tmpm->nid, VERB_CHAN_STREAM_ID_SET + 0x10);
|
||||||
|
'\n';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 HDCfgPopUpInfo(MyMass *tmpm)
|
||||||
|
{
|
||||||
|
U8 buf[STR_LEN];
|
||||||
|
StrPrint(buf,
|
||||||
|
"HDCfgPopUpInfoTask(0x%X);\"\\n\\nPress SHIFT-ESC\\n\\n\\n\\n\";View;",
|
||||||
|
tmpm);
|
||||||
|
Fs->win_inhibit |= WIF_SELF_ODE;
|
||||||
|
Fs->draw_it = NULL;
|
||||||
|
Refresh;
|
||||||
|
PopUp(buf, Fs);
|
||||||
|
Fs->win_inhibit &= ~WIF_SELF_ODE;
|
||||||
|
Fs->draw_it = &DrawIt;
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 HDCfgEdLink(MyMass *tmpm_out, MyMass *tmpm_in)
|
||||||
|
{
|
||||||
|
I64 i, j;
|
||||||
|
if ((i = FindConnectIndex(tmpm_in, tmpm_out->nid)) >= 0)
|
||||||
|
{
|
||||||
|
switch (tmpm_in->type)
|
||||||
|
{
|
||||||
|
case AWT_MIXER:
|
||||||
|
MemSet(tmpm_in->gain_lst, 0x80, sizeof(U8) *CONNECTS_NUM);
|
||||||
|
tmpm_in->gain_lst[i] = 0x7F;
|
||||||
|
for (j = 0; j < tmpm_in->num_connects; j++)
|
||||||
|
HDWriteCORBSync(hda.cad, tmpm_in->nid,
|
||||||
|
VERB_AMPLIFIER_GAIN_SET + 0x7000 + tmpm_in->gain_lst[j] + j << 8);
|
||||||
|
break;
|
||||||
|
case AWT_INPUT:
|
||||||
|
case AWT_SELECTOR:
|
||||||
|
case AWT_PIN_COMPLEX:
|
||||||
|
case AWT_VENDOR:
|
||||||
|
tmpm_in->cur_connect = i;
|
||||||
|
HDWriteCORBSync(hda.cad, tmpm_in->nid, VERB_CONNECT_SEL_SET + i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
RedoSprings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 HDCfgSave()
|
||||||
|
{
|
||||||
|
CDoc *doc = DocNew;
|
||||||
|
I64 i;
|
||||||
|
MyMass * tmpm;
|
||||||
|
DocPrint(doc, "//This file was generated by "
|
||||||
|
"$$LK,\"::/TempleOS/Adam/Sound/HDCfg.ZC.Z\","
|
||||||
|
"\"FI:::/TempleOS/Adam/Sound/HDCfg.ZC\"$$\n\n"
|
||||||
|
"U0 MyHDCfg()\n{\n");
|
||||||
|
tmpm = ode->next_mass;
|
||||||
|
while (tmpm != &ode->next_mass)
|
||||||
|
{
|
||||||
|
DocPrint(doc, " //0x%02X %Z\n", tmpm->nid, tmpm->type,
|
||||||
|
"ST_AUDIO_WIDGET_TYPES");
|
||||||
|
if (tmpm->num_connects)
|
||||||
|
{
|
||||||
|
DocPrint(doc, "//Connection Lst:");
|
||||||
|
for (i = 0; i < tmpm->num_connects; i++)
|
||||||
|
{
|
||||||
|
if (i == tmpm->cur_connect)
|
||||||
|
DocPrint(doc, "*");
|
||||||
|
DocPrint(doc, "0x%02X ", tmpm->connect_lst[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
DocPrint(doc, "\n");
|
||||||
|
if (tmpm->type == AWT_MIXER)
|
||||||
|
{
|
||||||
|
DocPrint(doc, "//Gain Lst:");
|
||||||
|
for (i = 0; i < tmpm->num_connects; i++)
|
||||||
|
DocPrint(doc, "0x%02X ", tmpm->gain_lst[i]);
|
||||||
|
DocPrint(doc, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (tmpm->type)
|
||||||
|
{
|
||||||
|
case AWT_OUTPUT:
|
||||||
|
if (tmpm->disabled)
|
||||||
|
DocPrint(doc,
|
||||||
|
"HDWriteCORBSync(hda.cad,0x%02X,"
|
||||||
|
"VERB_CHAN_STREAM_ID_SET+0x00);\n",
|
||||||
|
tmpm->nid);
|
||||||
|
else
|
||||||
|
DocPrint(doc,
|
||||||
|
"HDWriteCORBSync(hda.cad,0x%02X,"
|
||||||
|
"VERB_CHAN_STREAM_ID_SET+0x10);\n",
|
||||||
|
tmpm->nid);
|
||||||
|
break;
|
||||||
|
case AWT_MIXER:
|
||||||
|
DocPrint(doc,
|
||||||
|
"HDWriteCORBSync(hda.cad,0x%02X,"
|
||||||
|
"VERB_AMPLIFIER_GAIN_SET+0xB07F);\n",
|
||||||
|
tmpm->nid);
|
||||||
|
for (i = 0; i < tmpm->num_connects; i++)
|
||||||
|
DocPrint(doc,
|
||||||
|
"HDWriteCORBSync(hda.cad,0x%02X,"
|
||||||
|
"VERB_AMPLIFIER_GAIN_SET+0x%04X);\n",
|
||||||
|
tmpm->nid, 0x7000 + tmpm->gain_lst[i] + i << 8);
|
||||||
|
break;
|
||||||
|
case AWT_INPUT:
|
||||||
|
if (tmpm->disabled)
|
||||||
|
DocPrint(doc,
|
||||||
|
"HDWriteCORBSync(hda.cad,0x%02X,"
|
||||||
|
"VERB_CHAN_STREAM_ID_SET+0x00);\n",
|
||||||
|
tmpm->nid);
|
||||||
|
else
|
||||||
|
DocPrint(doc,
|
||||||
|
"HDWriteCORBSync(hda.cad,0x%02X,"
|
||||||
|
"VERB_CHAN_STREAM_ID_SET+0x20);\n",
|
||||||
|
tmpm->nid);
|
||||||
|
goto here;
|
||||||
|
case AWT_PIN_COMPLEX:
|
||||||
|
DocPrint(doc,
|
||||||
|
"HDWriteCORBSync(hda.cad,0x%02X,"
|
||||||
|
"VERB_PIN_WIDGET_CTL_SET+0x%02X);\n",
|
||||||
|
tmpm->nid, tmpm->pin_widget_ctl);
|
||||||
|
case AWT_SELECTOR:
|
||||||
|
case AWT_VENDOR:
|
||||||
|
here:
|
||||||
|
if (tmpm->num_connects > 1)
|
||||||
|
DocPrint(doc,
|
||||||
|
"HDWriteCORBSync(hda.cad,0x%02X,"
|
||||||
|
"VERB_CONNECT_SEL_SET+0x%02X);\n",
|
||||||
|
tmpm->nid, tmpm->cur_connect);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DocPrint(doc, "\n");
|
||||||
|
tmpm = tmpm->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
DocPrint(doc, "LBtr(&sys_semas[SEMA_SND],0);\n"
|
||||||
|
"}\n\nif (snd_dev==SD_HD_AUDIO)\n"
|
||||||
|
"MyHDCfg;\n");
|
||||||
|
StrCopy(doc->filename.name, "~/HDAudioCfg.ZC.Z");
|
||||||
|
DocWrite(doc);
|
||||||
|
DocDel(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 HDCfg()
|
||||||
|
{
|
||||||
|
I64 arg1, arg2;
|
||||||
|
MyMass *tmpm1 = NULL, *tmpm2 = NULL;
|
||||||
|
|
||||||
|
if (snd_dev != SD_HD_AUDIO)
|
||||||
|
{
|
||||||
|
"HD Audio not detected\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MenuPush( "File {"
|
||||||
|
" Abort(,CH_SHIFT_ESC);"
|
||||||
|
" Exit(,CH_ESC);"
|
||||||
|
"}"
|
||||||
|
"Edit {"
|
||||||
|
" Randomize(,'\n');"
|
||||||
|
" Options(,CH_SPACE);"
|
||||||
|
"}"
|
||||||
|
);
|
||||||
|
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
|
||||||
|
DocBottom;
|
||||||
|
AutoComplete;
|
||||||
|
WinBorder;
|
||||||
|
WinMax;
|
||||||
|
DocCursor;
|
||||||
|
DocClear;
|
||||||
|
Fs->win_inhibit = WIF_SELF_MS_L | WIF_SELF_MS_R | WIG_DBL_CLICK | WIF_SELF_DOC;
|
||||||
|
Init;
|
||||||
|
|
||||||
|
HDCfgTraverse(hda.cad, 0);
|
||||||
|
HDCfgRandomizeXY;
|
||||||
|
RedoSprings;
|
||||||
|
Fs->draw_it = &DrawIt;
|
||||||
|
PopUpOk( "This is a tool to cfgure\n"
|
||||||
|
"HD Audio.It creates $$FG,RED$$~/HDAudioCfg.ZC.Z$$FG$$\n"
|
||||||
|
"which you should $$FG,GREEN$$
|
||||||
|
#include$$FG$$ in your\n"
|
||||||
|
"$$FG,RED$$~/HomeSnd.ZC.Z$$FG$$ file.\n\n\n"
|
||||||
|
"Left click to see info and cfgure a widget.\n"
|
||||||
|
"Right click drag to connect output to input.\n\n"
|
||||||
|
"You will need to set input and output amplifier\n"
|
||||||
|
"gains by hand -- edit $$FG,RED$$~/HDAudioCfg.ZC.Z$$FG$$.\n\n"
|
||||||
|
"The $$FG,BLUE$$BLUE$$FG$$ line in the middle is microphone waveform.\n\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
HDRun(TRUE, TRUE); //run input output
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
switch (MessageGet(&arg1, &arg2,
|
||||||
|
1 << MESSAGE_MS_L_UP | 1 << MESSAGE_MS_R_DOWN | 1 << MESSAGE_MS_R_UP | 1 << MESSAGE_KEY_DOWN))
|
||||||
|
{
|
||||||
|
case MESSAGE_MS_L_UP:
|
||||||
|
if (tmpm1 = FindMassByXY(arg1, arg2))
|
||||||
|
HDCfgPopUpInfo(tmpm1);
|
||||||
|
tmpm1 = NULL;
|
||||||
|
break;
|
||||||
|
case MESSAGE_MS_R_DOWN:
|
||||||
|
tmpm1 = FindMassByXY(arg1, arg2);
|
||||||
|
break;
|
||||||
|
case MESSAGE_MS_R_UP:
|
||||||
|
tmpm2 = FindMassByXY(arg1, arg2);
|
||||||
|
if (tmpm1 && tmpm2)
|
||||||
|
HDCfgEdLink(tmpm1, tmpm2);
|
||||||
|
break;
|
||||||
|
case MESSAGE_KEY_DOWN:
|
||||||
|
switch (arg1)
|
||||||
|
{
|
||||||
|
case CH_SPACE:
|
||||||
|
if (tmpm1 = FindMassByXY( mouse.pos.x - Fs->pix_left - Fs->scroll_x,
|
||||||
|
mouse.pos.y - Fs->pix_top - Fs->scroll_y))
|
||||||
|
HDCfgPopUpInfo(tmpm1);
|
||||||
|
tmpm1 = NULL;
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
HDCfgRandomizeXY;
|
||||||
|
break;
|
||||||
|
case CH_ESC:
|
||||||
|
HDCfgSave;
|
||||||
|
case CH_SHIFT_ESC:
|
||||||
|
goto hd_done;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hd_done: //Don't goto out of try
|
||||||
|
MessageGet(,, 1 << MESSAGE_KEY_UP);
|
||||||
|
}
|
||||||
|
|
||||||
|
catch
|
||||||
|
Fs->catch_except = TRUE;
|
||||||
|
SettingsPop;
|
||||||
|
HDStop(TRUE, FALSE); //stop input
|
||||||
|
CleanUp;
|
||||||
|
MenuPop;
|
||||||
|
"$$BK,1$$Note:
|
||||||
|
#include \"~/HDAudioCfg\" in your start-up scripts."
|
||||||
|
"$$BK,0$$\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
HDCfg;
|
21
src/Home/Sound/HDAudio1/Sup1Snd/MakeSnd.ZC
Normal file
21
src/Home/Sound/HDAudio1/Sup1Snd/MakeSnd.ZC
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
Cd(__DIR__);;
|
||||||
|
|
||||||
|
#help_index "Sound"
|
||||||
|
class CSndWaveCtrl
|
||||||
|
{
|
||||||
|
I64 sample_rate,sample_bits,channels;
|
||||||
|
F64 freq_multiplier,amp_multiplier;
|
||||||
|
F64 phase,last_y,last_dydt,next_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
public U0 SoundTaskEndCB()
|
||||||
|
{//Will turn-off snd when a task gets killed.
|
||||||
|
Sound;
|
||||||
|
Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "SndMath"
|
||||||
|
#include "SndMusic"
|
||||||
|
#include "SndEffects"
|
||||||
|
#include "SndFile"
|
||||||
|
Cd("..");;
|
80
src/Home/Sound/HDAudio1/Sup1Snd/SndEffects.ZC
Normal file
80
src/Home/Sound/HDAudio1/Sup1Snd/SndEffects.ZC
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
#help_index "Sound"
|
||||||
|
|
||||||
|
#define SE_NOISE 0
|
||||||
|
#define SE_SWEEP 1
|
||||||
|
|
||||||
|
class CSoundEffectFrame
|
||||||
|
{
|
||||||
|
I32 type;
|
||||||
|
I8 ona1,ona2;
|
||||||
|
F64 duration;
|
||||||
|
};
|
||||||
|
|
||||||
|
U0 SoundEffectEndTaskCB()
|
||||||
|
{
|
||||||
|
Free(FramePtr("CSoundEffectFrame"));
|
||||||
|
music.mute--;
|
||||||
|
SoundTaskEndCB;
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 SoundEffectTask(CSoundEffectFrame *ns)
|
||||||
|
{
|
||||||
|
I64 i,ona;
|
||||||
|
F64 t0=tS,t,timeout=t0+ns->duration;
|
||||||
|
FramePtrAdd("CSoundEffectFrame",ns);
|
||||||
|
Fs->task_end_cb=&SoundEffectEndTaskCB;
|
||||||
|
switch (ns->type) {
|
||||||
|
case SE_NOISE:
|
||||||
|
i=MaxI64(ns->ona2-ns->ona1,1);
|
||||||
|
while (tS<timeout) {
|
||||||
|
ona=RandU16%i+ns->ona1;
|
||||||
|
Sound(ona);
|
||||||
|
t=Clamp(3000.0/Ona2Freq(ona),1.0,50.0);
|
||||||
|
if (t+tS>timeout)
|
||||||
|
t=timeout-tS;
|
||||||
|
Sleep(t);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SE_SWEEP:
|
||||||
|
while (tS<timeout) {
|
||||||
|
t=(tS-t0)/ns->duration;
|
||||||
|
ona=(1.0-t)*ns->ona1+t*ns->ona2;
|
||||||
|
Sound(ona);
|
||||||
|
t=Clamp(3000.0/Ona2Freq(ona),1.0,50.0);
|
||||||
|
if (t+tS>timeout)
|
||||||
|
t=timeout-tS;
|
||||||
|
Sleep(t);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CTask *Noise(I64 mS,F64 min_ona,F64 max_ona)
|
||||||
|
{//Make white noise for given number of mS.
|
||||||
|
CSoundEffectFrame *ns;
|
||||||
|
if (mS>0) {
|
||||||
|
ns=MAlloc(sizeof(CSoundEffectFrame));
|
||||||
|
ns->type=SE_NOISE;
|
||||||
|
ns->duration=mS/1000.0;
|
||||||
|
ns->ona1=min_ona;
|
||||||
|
ns->ona2=max_ona;
|
||||||
|
music.mute++;
|
||||||
|
return Spawn(&SoundEffectTask,ns,"Noise",,Fs);
|
||||||
|
} else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CTask *Sweep(I64 mS,F64 ona1,F64 ona2)
|
||||||
|
{//Sweep through freq range in given number of mS.
|
||||||
|
CSoundEffectFrame *ns;
|
||||||
|
if (mS>0) {
|
||||||
|
ns=MAlloc(sizeof(CSoundEffectFrame));
|
||||||
|
ns->type=SE_SWEEP;
|
||||||
|
ns->duration=mS/1000.0;
|
||||||
|
ns->ona1=ona1;
|
||||||
|
ns->ona2=ona2;
|
||||||
|
music.mute++;
|
||||||
|
return Spawn(&SoundEffectTask,ns,"Noise",,Fs);
|
||||||
|
} else
|
||||||
|
return NULL;
|
||||||
|
}
|
137
src/Home/Sound/HDAudio1/Sup1Snd/SndFile.ZC
Normal file
137
src/Home/Sound/HDAudio1/Sup1Snd/SndFile.ZC
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
#help_index "Sound/Sound Files"
|
||||||
|
#define SNDFILE_SAMPLE_RATE 8000
|
||||||
|
//Header for a ".SND" file
|
||||||
|
class CFileSND
|
||||||
|
{//big endian
|
||||||
|
U32 signature; //0x646e732e
|
||||||
|
U32 offset; //24
|
||||||
|
U32 data_size;
|
||||||
|
U32 coding; //3=16bit uncompressed
|
||||||
|
U32 sample_rate; //Hz
|
||||||
|
U32 channels; //1=mono
|
||||||
|
I16 body[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
//Windows media constraint.
|
||||||
|
//#define SND_FILE_DATA_MAX 0x0007FF00
|
||||||
|
#define SND_FILE_DATA_MAX 0x7FFFFF00
|
||||||
|
|
||||||
|
public I64 SndFileCreate(U8 *base_filename,F64 normalized_vol=1.0,
|
||||||
|
F64 averaging=0.0,I64 waveform=WF_SQUARE,
|
||||||
|
F64 reverb_delay=0,F64 reverb_intensity=0,F64 time_shift=0)
|
||||||
|
{//Use "screencast.record" flag to start or stop recording, then call this routine.
|
||||||
|
//Averaging should be a num from 0.0 to 0.999.
|
||||||
|
//Vol should be from 0.0 to 1.0.
|
||||||
|
//Set reverb_delay to like 0.3 sec and reverb_intensity to like 0.4.
|
||||||
|
I64 i,i1,k,cnt,cnt2,level,file_num;
|
||||||
|
F64 avg,dt;
|
||||||
|
CFileSND *s;
|
||||||
|
CSndWaveCtrl *swc=SndWaveCtrlNew(SNDFILE_SAMPLE_RATE,16,1);
|
||||||
|
CSoundData *d,*d1;
|
||||||
|
U8 *name,*name2;
|
||||||
|
|
||||||
|
screencast.record=FALSE;
|
||||||
|
|
||||||
|
dt=screencast.sound_head.last->tS-screencast.sound_head.next->tS;
|
||||||
|
if (!dt) return 0;
|
||||||
|
cnt=dt*SNDFILE_SAMPLE_RATE;
|
||||||
|
cnt++; //Terminator
|
||||||
|
|
||||||
|
name=StrNew(base_filename);
|
||||||
|
FileExtRemove(name);
|
||||||
|
|
||||||
|
s=CAlloc(offset(CFileSND.body)+cnt*sizeof(I16));
|
||||||
|
s->signature=0x646e732e;
|
||||||
|
s->offset=EndianU32(offset(CFileSND.body));
|
||||||
|
s->coding=EndianU32(3);
|
||||||
|
s->sample_rate=EndianU32(SNDFILE_SAMPLE_RATE);
|
||||||
|
s->channels=EndianU32(1);
|
||||||
|
|
||||||
|
if (time_shift) {
|
||||||
|
d=screencast.sound_head.next;
|
||||||
|
d->tS-=time_shift;
|
||||||
|
while (d->next!=&screencast.sound_head) {
|
||||||
|
d1=d->next;
|
||||||
|
dt=d1->tS-d->tS;
|
||||||
|
if (dt<0) {
|
||||||
|
QueueRemove(d1);
|
||||||
|
Free(d1);
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
d=screencast.sound_head.next;
|
||||||
|
k=0;
|
||||||
|
i=d->tS*SNDFILE_SAMPLE_RATE;
|
||||||
|
while (d->next!=&screencast.sound_head) {
|
||||||
|
d1=d->next;
|
||||||
|
i1=d1->tS*SNDFILE_SAMPLE_RATE;
|
||||||
|
if (i1-i) {
|
||||||
|
SndWaveAddBuf(swc,&s->body[k],i1-i,
|
||||||
|
Ona2Freq(d->ona),waveform,normalized_vol);
|
||||||
|
k+=i1-i;
|
||||||
|
i=i1;
|
||||||
|
}
|
||||||
|
QueueRemove(d);
|
||||||
|
Free(d);
|
||||||
|
d=d1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Average
|
||||||
|
if (averaging) {
|
||||||
|
avg=0;
|
||||||
|
for (i=0;i<cnt-1;i++)
|
||||||
|
s->body[i]=avg=LowPass1(averaging,avg,s->body[i],1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Reverb
|
||||||
|
if (reverb_intensity) {
|
||||||
|
if (dt=reverb_delay*SNDFILE_SAMPLE_RATE)
|
||||||
|
for (i=dt;i<cnt;i++)
|
||||||
|
s->body[i]+=reverb_intensity*s->body[i-dt];
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get rid of D.C. component
|
||||||
|
for (k=0;k<3;k++) {
|
||||||
|
level=0;
|
||||||
|
for (i=0;i<cnt-1;i++)
|
||||||
|
level+=s->body[i];
|
||||||
|
level/=cnt-1;
|
||||||
|
for (i=0;i<cnt-1;i++)
|
||||||
|
s->body[i]=ClampI64(s->body[i]-level,I16_MIN,I16_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0;i<cnt-1;i++)
|
||||||
|
s->body[i]=EndianU16(s->body[i]);
|
||||||
|
|
||||||
|
s->body[cnt-1]=0;
|
||||||
|
|
||||||
|
d=screencast.sound_head.next;
|
||||||
|
while (d!=&screencast.sound_head) {
|
||||||
|
d1=d->next;
|
||||||
|
QueueRemove(d);
|
||||||
|
Free(d);
|
||||||
|
d=d1;
|
||||||
|
}
|
||||||
|
|
||||||
|
name2=MAlloc(StrLen(name)+3+1+3+1);
|
||||||
|
cnt2=cnt;
|
||||||
|
file_num=0;
|
||||||
|
while (cnt2>0) {
|
||||||
|
i=cnt2;
|
||||||
|
if (i>SND_FILE_DATA_MAX)
|
||||||
|
i=SND_FILE_DATA_MAX;
|
||||||
|
s->data_size=EndianU32(i*sizeof(I16));
|
||||||
|
MemCopy(s->body,&s->body[file_num*SND_FILE_DATA_MAX],i*sizeof(I16));
|
||||||
|
StrPrint(name2,"%s%03d.SND",name,file_num++);
|
||||||
|
FileWrite(name2,s,offset(CFileSND.body)+i*sizeof(I16));
|
||||||
|
cnt2-=i;
|
||||||
|
}
|
||||||
|
Free(s);
|
||||||
|
Free(name);
|
||||||
|
Free(name2);
|
||||||
|
|
||||||
|
SndWaveCtrlDel(swc);
|
||||||
|
return cnt;
|
||||||
|
}
|
248
src/Home/Sound/HDAudio1/Sup1Snd/SndMath.ZC
Normal file
248
src/Home/Sound/HDAudio1/Sup1Snd/SndMath.ZC
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
#help_index "Sound/Math;Math"
|
||||||
|
public F64 Saw(F64 t,F64 period)
|
||||||
|
{//Sawtooth. 0.0 - 1.0 think "(Sin+1)/2"
|
||||||
|
if (period) {
|
||||||
|
if (t>=0.0)
|
||||||
|
return t%period/period;
|
||||||
|
else
|
||||||
|
return 1.0+t%period/period;
|
||||||
|
} else
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public F64 FullSaw(F64 t,F64 period)
|
||||||
|
{//Plus&Minus Sawtooth. 1.0 - -1.0 think "Sin"
|
||||||
|
if (period) {
|
||||||
|
if (t>=0.0)
|
||||||
|
return 2.0*(t%period/period)-1.0;
|
||||||
|
else
|
||||||
|
return 2.0*(t%period/period)+1.0;
|
||||||
|
} else
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public F64 Caw(F64 t,F64 period)
|
||||||
|
{//Cawtooth. 1.0 - 0.0 think "(Cos+1)/2"
|
||||||
|
if (period) {
|
||||||
|
if (t>=0.0)
|
||||||
|
return 1.0-t%period/period;
|
||||||
|
else
|
||||||
|
return -(t%period)/period;
|
||||||
|
} else
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public F64 FullCaw(F64 t,F64 period)
|
||||||
|
{//Plus&Minus Cawtooth. 1.0 - -1.0 think "Cos"
|
||||||
|
if (period) {
|
||||||
|
if (t>=0.0)
|
||||||
|
return -2.0*(t%period/period)+1.0;
|
||||||
|
else
|
||||||
|
return -2.0*(t%period/period)-1.0;
|
||||||
|
} else
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public F64 Tri(F64 t,F64 period)
|
||||||
|
{//Triangle waveform. 0.0 - 1.0 - 0.0
|
||||||
|
if (period) {
|
||||||
|
t=2.0*(Abs(t)%period)/period;
|
||||||
|
if (t<=1.0)
|
||||||
|
return t;
|
||||||
|
else
|
||||||
|
return 2.0-t;
|
||||||
|
} else
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public F64 FullTri(F64 t,F64 period)
|
||||||
|
{//Plus&Minus Triangle waveform. 0.0 - 1.0 - 0.0 - -1.0 -0.0
|
||||||
|
if (period) {
|
||||||
|
t=4.0*(t%period)/period;
|
||||||
|
if (t<=-1.0) {
|
||||||
|
if (t<=-3.0)
|
||||||
|
return t+4.0;
|
||||||
|
else
|
||||||
|
return -2.0-t;
|
||||||
|
} else {
|
||||||
|
if (t<=1.0)
|
||||||
|
return t;
|
||||||
|
else if (t<=3.0)
|
||||||
|
return 2.0-t;
|
||||||
|
else
|
||||||
|
return t-4.0;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#help_index "Sound/Math"
|
||||||
|
|
||||||
|
public I8 Note2Ona(I64 note,I64 octave=4)
|
||||||
|
{//Note to ona. Mid C is ona=51, note=3 and octave=4.
|
||||||
|
if (note<3)
|
||||||
|
return (octave+1)*12+note;
|
||||||
|
else
|
||||||
|
return octave*12+note;
|
||||||
|
}
|
||||||
|
|
||||||
|
public I8 Ona2Note(I8 ona)
|
||||||
|
{//Ona to note in octave. Mid C is ona=51, note=3 and octave=4.
|
||||||
|
return ona%12;
|
||||||
|
}
|
||||||
|
|
||||||
|
public I8 Ona2Octave(I8 ona)
|
||||||
|
{//Ona to octave. Mid C is ona=51, note=3 and octave=4.
|
||||||
|
I64 note=ona%12,octave=ona/12;
|
||||||
|
if (note<3)
|
||||||
|
return octave-1;
|
||||||
|
else
|
||||||
|
return octave;
|
||||||
|
}
|
||||||
|
|
||||||
|
F64 SinPhaseCont(F64 last_y,F64 last_dydt,
|
||||||
|
F64 current_amp,F64 phase_offset)
|
||||||
|
{//Next sample of sin waveform.
|
||||||
|
F64 phase;
|
||||||
|
phase=last_y/current_amp;
|
||||||
|
if (phase>1.0) phase=1.0;
|
||||||
|
if (phase<-1.0) phase=-1.0;
|
||||||
|
if (last_dydt<0)
|
||||||
|
phase=ã-ASin(phase);
|
||||||
|
else
|
||||||
|
phase=ASin(phase);
|
||||||
|
return phase-phase_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CSndWaveCtrl *SndWaveCtrlNew(I64 sample_rate=8000,I64 sample_bits=24,
|
||||||
|
I64 channels=2,CTask *mem_task=NULL)
|
||||||
|
{//MAlloc ctrl struct for generating waveforms.
|
||||||
|
CSndWaveCtrl *swc=CAlloc(sizeof(CSndWaveCtrl),mem_task);
|
||||||
|
swc->freq_multiplier=1.0;
|
||||||
|
swc->amp_multiplier=1.0;
|
||||||
|
swc->sample_rate=sample_rate;
|
||||||
|
swc->sample_bits=sample_bits;
|
||||||
|
swc->channels=channels;
|
||||||
|
swc->last_dydt=1.0;
|
||||||
|
return swc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public U0 SndWaveCtrlDel(CSndWaveCtrl *swc)
|
||||||
|
{//Free waveform ctrl.
|
||||||
|
Free(swc);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define WF_NULL 0
|
||||||
|
#define WF_SQUARE 1
|
||||||
|
#define WF_SINE 2
|
||||||
|
#define WF_TRI 3
|
||||||
|
#define WF_SAWTOOTH 4
|
||||||
|
#define WF_NOISE 5
|
||||||
|
#define WF_WAVEFORMS_NUM 6
|
||||||
|
|
||||||
|
public U0 SndWaveAddBuf(CSndWaveCtrl *swc,U8 *buf,I64 num_samples,
|
||||||
|
F64 _freq,I64 _waveform=WF_SQUARE,F64 _amp=1.0,F64 _left=1.0, F64 _right=1.0)
|
||||||
|
{//Add waveform to buffer.
|
||||||
|
//num_samples is multiplied by channels to get buf_len.
|
||||||
|
//left,right range from 0.0-1.0
|
||||||
|
//Supports 16,24 and 32 bits
|
||||||
|
I64 reg i,reg j,reg k;
|
||||||
|
F64 a,f,amp,reg phase;
|
||||||
|
if (!swc) return;
|
||||||
|
_freq*=swc->freq_multiplier;
|
||||||
|
_amp*=swc->amp_multiplier;
|
||||||
|
if (!_freq||!_amp) {
|
||||||
|
swc->last_y=swc->phase=0;
|
||||||
|
swc->last_dydt=1.0;
|
||||||
|
} else {
|
||||||
|
phase=swc->phase;
|
||||||
|
i=0;
|
||||||
|
amp=Min(I32_MAX,I32_MAX*_amp);
|
||||||
|
f=2*ã/swc->sample_rate*_freq;
|
||||||
|
switch (_waveform) {
|
||||||
|
case WF_NOISE:
|
||||||
|
a=2.0/ã*amp;
|
||||||
|
break;
|
||||||
|
case WF_SAWTOOTH:
|
||||||
|
a=amp/ã;
|
||||||
|
break;
|
||||||
|
case WF_SINE:
|
||||||
|
phase=SinPhaseCont(swc->last_y,swc->last_dydt,amp,0.0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
while (phase<0)
|
||||||
|
phase+=2*ã;
|
||||||
|
while (phase>=2*ã)
|
||||||
|
phase-=2*ã;
|
||||||
|
num_samples*=swc->channels;
|
||||||
|
while (i<num_samples) {
|
||||||
|
switch (_waveform) {
|
||||||
|
case WF_SQUARE:
|
||||||
|
if (phase>=ã)
|
||||||
|
j=-amp;
|
||||||
|
else
|
||||||
|
j=amp;
|
||||||
|
break;
|
||||||
|
case WF_SINE:
|
||||||
|
j=amp*Sin(phase);
|
||||||
|
break;
|
||||||
|
case WF_TRI:
|
||||||
|
if (phase>=ã) {
|
||||||
|
swc->last_y=swc->next_y;
|
||||||
|
swc->next_y=-amp*Sign(swc->last_y)+.00001;
|
||||||
|
phase-=ã;
|
||||||
|
}
|
||||||
|
j=(swc->last_y*(ã-phase)+swc->next_y*phase)/ã;
|
||||||
|
break;
|
||||||
|
case WF_SAWTOOTH:
|
||||||
|
j=a*(phase-ã);
|
||||||
|
break;
|
||||||
|
case WF_NOISE:
|
||||||
|
if (phase<ã) {
|
||||||
|
if (phase<f) {
|
||||||
|
swc->last_y=swc->next_y;
|
||||||
|
swc->next_y=a*RandI16/U16_MAX;
|
||||||
|
}
|
||||||
|
j=swc->last_y*(ã-phase)+swc->next_y*phase;
|
||||||
|
} else {
|
||||||
|
if (phase-ã<f) {
|
||||||
|
swc->last_y=swc->next_y;
|
||||||
|
swc->next_y=a*RandI16/U16_MAX;
|
||||||
|
}
|
||||||
|
j=swc->last_y*(2.0*ã-phase)+swc->next_y*(phase-ã);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//left channel
|
||||||
|
k=j*_left;
|
||||||
|
if (swc->sample_bits==16) {
|
||||||
|
k>>=16;
|
||||||
|
buf(I16 *)[i++]+=k;
|
||||||
|
} else {
|
||||||
|
if (swc->sample_bits==24)
|
||||||
|
k&=0xFFFFFF00;
|
||||||
|
buf(I32 *)[i++]+=k;
|
||||||
|
}
|
||||||
|
//right channel
|
||||||
|
if (swc->channels==2) {
|
||||||
|
k=j*_right;
|
||||||
|
if (swc->sample_bits==16) {
|
||||||
|
k>>=16;
|
||||||
|
buf(I16 *)[i++]+=k;
|
||||||
|
} else {
|
||||||
|
if (swc->sample_bits==24)
|
||||||
|
k&=0xFFFFFF00;
|
||||||
|
buf(I32 *)[i++]+=k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
phase+=f;
|
||||||
|
while (phase>=2*ã)
|
||||||
|
phase-=2*ã;
|
||||||
|
}
|
||||||
|
if (_waveform==WF_SINE) {
|
||||||
|
swc->last_y=amp*Sin(phase);
|
||||||
|
swc->last_dydt=Cos(phase);
|
||||||
|
}
|
||||||
|
swc->phase=phase;
|
||||||
|
}
|
||||||
|
}
|
224
src/Home/Sound/HDAudio1/Sup1Snd/SndMusic.ZC
Normal file
224
src/Home/Sound/HDAudio1/Sup1Snd/SndMusic.ZC
Normal file
|
@ -0,0 +1,224 @@
|
||||||
|
#help_index "Sound/Music"
|
||||||
|
|
||||||
|
public class CMusicGlbls
|
||||||
|
{
|
||||||
|
U8 *cur_song;
|
||||||
|
CTask *cur_song_task;
|
||||||
|
I64 octave;
|
||||||
|
F64 note_len;
|
||||||
|
U8 note_map[7];
|
||||||
|
Bool mute;
|
||||||
|
I64 meter_top,meter_bottom;
|
||||||
|
F64 tempo,stacatto_factor;
|
||||||
|
|
||||||
|
//If you wish to sync with a
|
||||||
|
//note in a Play() string. 0 is the start
|
||||||
|
I64 play_note_num;
|
||||||
|
|
||||||
|
F64 tM_correction,last_Beat,last_tM;
|
||||||
|
} music={NULL,NULL,4,1.0,{0,2,3,5,7,8,10},FALSE,4,4,2.5,0.9,0,0,0,0};
|
||||||
|
|
||||||
|
#help_index "Sound/Music;Time/Seconds"
|
||||||
|
public F64 tM()
|
||||||
|
{//Time in seconds synced to music subsystem.
|
||||||
|
return (counts.jiffies+music.tM_correction)/JIFFY_FREQ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public F64 Beat()
|
||||||
|
{//Time in music beats.
|
||||||
|
F64 res,cur_tM;
|
||||||
|
PUSHFD
|
||||||
|
CLI
|
||||||
|
if (mp_count>1)
|
||||||
|
while (LBts(&sys_semas[SEMA_TMBEAT],0))
|
||||||
|
PAUSE
|
||||||
|
cur_tM=tM;
|
||||||
|
res=music.last_Beat;
|
||||||
|
if (music.tempo)
|
||||||
|
res+=(cur_tM-music.last_tM)*music.tempo;
|
||||||
|
music.last_tM=cur_tM;
|
||||||
|
music.last_Beat=res;
|
||||||
|
LBtr(&sys_semas[SEMA_TMBEAT],0);
|
||||||
|
POPFD
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#help_index "Sound/Music"
|
||||||
|
U8 *MusicSetOctave(U8 *st)
|
||||||
|
{
|
||||||
|
I64 ch;
|
||||||
|
ch=*st++;
|
||||||
|
while ('0'<=ch<='9') {
|
||||||
|
music.octave=ch-'0';
|
||||||
|
ch=*st++;
|
||||||
|
}
|
||||||
|
return --st;
|
||||||
|
}
|
||||||
|
|
||||||
|
U8 *MusicSetMeter(U8 *st)
|
||||||
|
{
|
||||||
|
I64 ch;
|
||||||
|
ch=*st++;
|
||||||
|
while (ch=='M') {
|
||||||
|
ch=*st++;
|
||||||
|
if ('0'<=ch<='9') {
|
||||||
|
music.meter_top=ch-'0';
|
||||||
|
ch=*st++;
|
||||||
|
}
|
||||||
|
if (ch=='/')
|
||||||
|
ch=*st++;
|
||||||
|
if ('0'<=ch<='9') {
|
||||||
|
music.meter_bottom=ch-'0';
|
||||||
|
ch=*st++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return --st;
|
||||||
|
}
|
||||||
|
|
||||||
|
U8 *MusicSetNoteLen(U8 *st)
|
||||||
|
{
|
||||||
|
Bool cont=TRUE;
|
||||||
|
do {
|
||||||
|
switch (*st++) {
|
||||||
|
case 'w': music.note_len=4.0; break;
|
||||||
|
case 'h': music.note_len=2.0; break;
|
||||||
|
case 'q': music.note_len=1.0; break;
|
||||||
|
case 'e': music.note_len=0.5; break;
|
||||||
|
case 's': music.note_len=0.25; break;
|
||||||
|
case 't': music.note_len=2.0*music.note_len/3.0; break;
|
||||||
|
case '.': music.note_len=1.5*music.note_len; break;
|
||||||
|
default:
|
||||||
|
st--;
|
||||||
|
cont=FALSE;
|
||||||
|
}
|
||||||
|
} while (cont);
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
|
||||||
|
public U0 Play(U8 *st,U8 *words=NULL)
|
||||||
|
{/* Notes are entered with a capital letter.
|
||||||
|
|
||||||
|
Octaves are entered with a digit and
|
||||||
|
stay set until changed. Mid C is octave 4.
|
||||||
|
|
||||||
|
Durations are entered with
|
||||||
|
'w' whole note
|
||||||
|
'h' half note
|
||||||
|
'q' quarter note
|
||||||
|
'e' eighth note
|
||||||
|
't' sets to 2/3rds the current duration
|
||||||
|
'.' sets to 1.5 times the current duration
|
||||||
|
durations stay set until changed.
|
||||||
|
|
||||||
|
'(' tie, placed before the note to be extended
|
||||||
|
|
||||||
|
$LK,"music.meter_top",A="MN:CMusicGlbls"$,$LK,"music.meter_bottom",A="MN:CMusicGlbls"$ is set with
|
||||||
|
"M3/4"
|
||||||
|
"M4/4"
|
||||||
|
etc.
|
||||||
|
|
||||||
|
Sharp and flat are done with '#' or 'b'.
|
||||||
|
|
||||||
|
The var music.stacatto_factor can
|
||||||
|
be set to a range from 0.0 to 1.0.
|
||||||
|
|
||||||
|
The var music.tempo is quarter-notes
|
||||||
|
per second.It defaults to
|
||||||
|
2.5 and gets faster when bigger.
|
||||||
|
*/
|
||||||
|
U8 *word,*last_st;
|
||||||
|
I64 note,octave,i=0,ona,timeout_val,timeout_val2;
|
||||||
|
Bool tie;
|
||||||
|
F64 d,on_jiffies,off_jiffies;
|
||||||
|
music.play_note_num=0;
|
||||||
|
while (*st) {
|
||||||
|
timeout_val=counts.jiffies;
|
||||||
|
tie=FALSE;
|
||||||
|
|
||||||
|
do {
|
||||||
|
last_st=st;
|
||||||
|
if (*st=='(') {
|
||||||
|
tie=TRUE;
|
||||||
|
st++;
|
||||||
|
} else {
|
||||||
|
st=MusicSetMeter(st);
|
||||||
|
st=MusicSetOctave(st);
|
||||||
|
st=MusicSetNoteLen(st);
|
||||||
|
}
|
||||||
|
} while (st!=last_st);
|
||||||
|
|
||||||
|
if (!*st) break;
|
||||||
|
note=*st++-'A';
|
||||||
|
if (note<7) {
|
||||||
|
note=music.note_map[note];
|
||||||
|
octave=music.octave;
|
||||||
|
if (*st=='b') {
|
||||||
|
note--;
|
||||||
|
if (note==2)
|
||||||
|
octave--;
|
||||||
|
st++;
|
||||||
|
} else if (*st=='#') {
|
||||||
|
note++;
|
||||||
|
if (note==3)
|
||||||
|
octave++;
|
||||||
|
st++;
|
||||||
|
}
|
||||||
|
ona=Note2Ona(note,octave);
|
||||||
|
} else
|
||||||
|
ona=0;
|
||||||
|
if (words && (word=ListSub(i++,words)) && StrCompare(word,""))
|
||||||
|
"%s",word;
|
||||||
|
d=JIFFY_FREQ*music.note_len/music.tempo;
|
||||||
|
if (tie) {
|
||||||
|
on_jiffies =d;
|
||||||
|
off_jiffies =0;
|
||||||
|
} else {
|
||||||
|
on_jiffies =d*music.stacatto_factor;
|
||||||
|
off_jiffies =d*(1.0-music.stacatto_factor);
|
||||||
|
}
|
||||||
|
timeout_val+=on_jiffies;
|
||||||
|
timeout_val2=timeout_val+off_jiffies;
|
||||||
|
|
||||||
|
if (!music.mute)
|
||||||
|
Sound(ona);
|
||||||
|
SleepUntil(timeout_val);
|
||||||
|
music.tM_correction+=on_jiffies-ToI64(on_jiffies);
|
||||||
|
|
||||||
|
if (!music.mute)
|
||||||
|
Sound;
|
||||||
|
SleepUntil(timeout_val2);
|
||||||
|
music.tM_correction+=off_jiffies-ToI64(off_jiffies);
|
||||||
|
|
||||||
|
music.play_note_num++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U0 MusicSettingsReset()
|
||||||
|
{
|
||||||
|
music.play_note_num=0;
|
||||||
|
music.stacatto_factor=0.9;
|
||||||
|
music.tempo=2.5;
|
||||||
|
music.octave=4;
|
||||||
|
music.note_len=1.0;
|
||||||
|
music.meter_top=4;
|
||||||
|
music.meter_bottom=4;
|
||||||
|
SoundReset;
|
||||||
|
PUSHFD
|
||||||
|
CLI
|
||||||
|
if (mp_count>1)
|
||||||
|
while (LBts(&sys_semas[SEMA_TMBEAT],0))
|
||||||
|
PAUSE
|
||||||
|
music.last_tM=tM;
|
||||||
|
music.last_Beat=0.0;
|
||||||
|
LBtr(&sys_semas[SEMA_TMBEAT],0);
|
||||||
|
POPFD
|
||||||
|
}
|
||||||
|
|
||||||
|
MusicSettingsReset;
|
||||||
|
|
||||||
|
U0 CurSongTask()
|
||||||
|
{
|
||||||
|
Fs->task_end_cb=&SoundTaskEndCB;
|
||||||
|
while (TRUE)
|
||||||
|
Play(music.cur_song);
|
||||||
|
}
|
Loading…
Reference in a new issue