Speaker - First implementation

This commit is contained in:
tudnai 2020-05-09 23:40:37 -07:00
parent e96f7bafc9
commit cf2325e6fa
5 changed files with 171 additions and 1 deletions

View File

@ -70,6 +70,8 @@
3262F37723E169F8008BDB95 /* spk_up.wav in Resources */ = {isa = PBXBuildFile; fileRef = 3262F37523E169F8008BDB95 /* spk_up.wav */; };
32A9F72C24668D26004902A1 /* apple-rainbow.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 32A9F72B24668D26004902A1 /* apple-rainbow.jpg */; };
32A9F72D24668D26004902A1 /* apple-rainbow.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 32A9F72B24668D26004902A1 /* apple-rainbow.jpg */; };
32A9F74A2467B60B004902A1 /* speaker.c in Sources */ = {isa = PBXBuildFile; fileRef = 32A9F7492467B60B004902A1 /* speaker.c */; };
32A9F74B2467B60B004902A1 /* speaker.c in Sources */ = {isa = PBXBuildFile; fileRef = 32A9F7492467B60B004902A1 /* speaker.c */; };
32BFFB5B22EACC630003B53F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BFFB5A22EACC630003B53F /* AppDelegate.swift */; };
32BFFB5D22EACC630003B53F /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BFFB5C22EACC630003B53F /* ViewController.swift */; };
32BFFB5F22EACC660003B53F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 32BFFB5E22EACC660003B53F /* Assets.xcassets */; };
@ -189,6 +191,8 @@
326426112328ADF4008B615F /* Apple_II_ROM.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = Apple_II_ROM.s; sourceTree = "<group>"; };
326ED2EE232D7A0000A41337 /* 6502_functional_test.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; path = 6502_functional_test.bin; sourceTree = SOURCE_ROOT; };
32A9F72B24668D26004902A1 /* apple-rainbow.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "apple-rainbow.jpg"; sourceTree = "<group>"; };
32A9F7482467B60B004902A1 /* speaker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = speaker.h; sourceTree = "<group>"; };
32A9F7492467B60B004902A1 /* speaker.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = speaker.c; sourceTree = "<group>"; };
32B18435233F10BC00DBB4AB /* Shaders.metal */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.metal; path = Shaders.metal; sourceTree = "<group>"; };
32B18438233FAB3900DBB4AB /* verticies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = verticies.swift; sourceTree = "<group>"; };
32BFFB5722EACC630003B53F /* A2Mac.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = A2Mac.app; sourceTree = BUILT_PRODUCTS_DIR; };
@ -310,6 +314,7 @@
325EB63223F8862A00C6B4A4 /* dev */ = {
isa = PBXGroup;
children = (
32A9F7472467B5DF004902A1 /* audio */,
325EB63B23FA57C000C6B4A4 /* mem */,
325EB63323F8863100C6B4A4 /* disk */,
);
@ -419,6 +424,15 @@
path = Resources;
sourceTree = "<group>";
};
32A9F7472467B5DF004902A1 /* audio */ = {
isa = PBXGroup;
children = (
32A9F7492467B60B004902A1 /* speaker.c */,
32A9F7482467B60B004902A1 /* speaker.h */,
);
path = audio;
sourceTree = "<group>";
};
32BFFB4E22EACC630003B53F = {
isa = PBXGroup;
children = (
@ -816,6 +830,7 @@
buildActionMask = 2147483647;
files = (
325EB67623FBC44400C6B4A4 /* common.c in Sources */,
32A9F74B2467B60B004902A1 /* speaker.c in Sources */,
325EB67523FBC43E00C6B4A4 /* 6502.c in Sources */,
325EB67823FBC45300C6B4A4 /* disk.c in Sources */,
325EB64723FBBACF00C6B4A4 /* ViewController.swift in Sources */,
@ -849,6 +864,7 @@
32439F8722ECD8AD0077AAE0 /* 6502.c in Sources */,
325EB63623F8F78300C6B4A4 /* disk.c in Sources */,
325EB63923F9E48100C6B4A4 /* common.c in Sources */,
32A9F74A2467B60B004902A1 /* speaker.c in Sources */,
32BFFB5D22EACC630003B53F /* ViewController.swift in Sources */,
325EB69323FE6C6200C6B4A4 /* HiRes.swift in Sources */,
32C4532E233345430000EBA1 /* MonitorView.swift in Sources */,

View File

@ -15,6 +15,7 @@
#include <time.h>
#include "6502.h"
#include "../dev/disk/woz.h"
#include "speaker.h"
void ViewController_spk_up_play(void);
@ -712,6 +713,10 @@ void softReset() {
void m6502_Run() {
// clear speaker buffer, so we can fill it up by new data
memset(spkr_samples, 127, spkr_buf_size);
// init time
//#ifdef CLK_WAIT
// unsigned long long elpased = (unsigned long long)-1LL;
@ -772,6 +777,8 @@ void m6502_Run() {
}
}
spkr_play();
}
void read_rom( const char * bundlePath, const char * filename, uint8_t * rom, const uint16_t addr ) {
@ -845,6 +852,8 @@ void m6502_ColdReset( const char * bundlePath, const char * romFileName ) {
inst_cnt = 0;
mhz = (double)MHz_6502 / M;
spkr_init();
unsigned long long saved_frm_set = clk_6502_per_frm_set;
clk_6502_per_frm =
clk_6502_per_frm_max =

115
src/dev/audio/speaker.c Normal file
View File

@ -0,0 +1,115 @@
//
// speaker.c
// A2Mac
//
// Created by Tamas Rudnai on 5/9/20.
// Copyright © 2020 GameAlloy. All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#include "speaker.h"
#define CASE_RETURN(err) case (err): return #err
const char* al_err_str(ALenum err) {
switch(err) {
CASE_RETURN(AL_NO_ERROR);
CASE_RETURN(AL_INVALID_NAME);
CASE_RETURN(AL_INVALID_ENUM);
CASE_RETURN(AL_INVALID_VALUE);
CASE_RETURN(AL_INVALID_OPERATION);
CASE_RETURN(AL_OUT_OF_MEMORY);
}
return "unknown";
}
#undef CASE_RETURN
#define __al_check_error(file,line) \
do { \
ALenum err = alGetError(); \
for(; err != AL_NO_ERROR; err = alGetError()) { \
printf( "AL Error %s at %s:%d\n", al_err_str(err), file, line ); \
} \
} while(0)
#define al_check_error() \
__al_check_error(__FILE__, __LINE__)
ALCdevice *dev = NULL;
ALCcontext *ctx = NULL;
ALuint spkr_buf = 0;
ALuint spkr_src = 0;
const int spkr_seconds = 1;
const unsigned spkr_sample_rate = 44100;
const unsigned spkr_buf_size = spkr_seconds * spkr_sample_rate;
char spkr_samples [ spkr_buf_size ];
/* initialize OpenAL */
void spkr_init() {
const char *defname = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
printf( "Default device: %s\n", defname );
dev = alcOpenDevice(defname);
ctx = alcCreateContext(dev, NULL);
alcMakeContextCurrent(ctx);
// Fill buffer with zeros
memset( spkr_samples, 127, spkr_buf_size );
}
/* Dealloc OpenAL */
void spkr_exit() {
ALCdevice *dev = NULL;
ALCcontext *ctx = NULL;
ctx = alcGetCurrentContext();
dev = alcGetContextsDevice(ctx);
alcMakeContextCurrent(NULL);
alcDestroyContext(ctx);
alcCloseDevice(dev);
al_check_error();
}
void spkr_play() {
if ( spkr_src ) {
alSourceStop(spkr_src);
al_check_error();
alSourcei(spkr_src, AL_BUFFER, 0);
al_check_error();
}
if ( spkr_buf ) {
alDeleteBuffers(1, &spkr_buf);
al_check_error();
}
/* Create buffer to store samples */
spkr_buf = 0;
alGenBuffers(1, &spkr_buf);
al_check_error();
/* Download buffer to OpenAL */
alBufferData(spkr_buf, AL_FORMAT_MONO8, spkr_samples, spkr_buf_size, spkr_sample_rate);
al_check_error();
/* Set-up sound source and play buffer */
spkr_src = 0;
alGenSources(1, &spkr_src);
alSourcei(spkr_src, AL_BUFFER, spkr_buf);
alSourcei(spkr_src, AL_LOOPING, 0);
alSourcePlay(spkr_src);
}

23
src/dev/audio/speaker.h Normal file
View File

@ -0,0 +1,23 @@
//
// speaker.h
// A2Mac
//
// Created by Tamas Rudnai on 5/9/20.
// Copyright © 2020 GameAlloy. All rights reserved.
//
#ifndef speaker_h
#define speaker_h
#include <stdio.h>
extern void spkr_init(void);
extern void spkr_exit(void);
extern void spkr_play(void);
extern const unsigned spkr_buf_size;
extern char spkr_samples [];
#endif /* speaker_h */

View File

@ -13,6 +13,7 @@
#include "6502.h"
#include "disk.h"
#include "woz.h"
#include "speaker.h"
typedef union address16_u {
@ -418,9 +419,14 @@ INLINE uint8_t ioRead( uint16_t addr ) {
Apple2_64K_RAM[io_KBD] &= 0x7F;
return Apple2_64K_RAM[io_KBDSTRB];
case (uint8_t)io_SPKR:
case (uint8_t)io_SPKR: {
// TODO: This is very slow!
// printf("io_KBDSTRB\n");
// push a click into the speaker buffer
// (we will play the entire buffer at the end of the frame)
int sample_idx = clkfrm / 22;
spkr_samples[sample_idx] = 0;
//ViewController_spk_up_play();
@ -434,6 +440,7 @@ INLINE uint8_t ioRead( uint16_t addr ) {
// videoMode.col80 = 1;
// break;
//
}
case (uint8_t)io_VID_RDTEXT:
return videoMode.text << 7;