mirror of https://github.com/trudnai/Steve2.git
Speaker - First implementation
This commit is contained in:
parent
e96f7bafc9
commit
cf2325e6fa
|
@ -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 */,
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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 */
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue