mirror of
https://github.com/86Box/86Box.git
synced 2026-02-23 09:58:19 -07:00
Merge remote-tracking branch '86box/v0.5_fdd_audio_multitrack_seek_sound_effects'
This commit is contained in:
BIN
86box/86Box.exe
Normal file
BIN
86box/86Box.exe
Normal file
Binary file not shown.
0
src/.vs/CMake Overview
Normal file
0
src/.vs/CMake Overview
Normal file
3
src/.vs/ProjectSettings.json
Normal file
3
src/.vs/ProjectSettings.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"CurrentProjectSetting": "x64-Debug"
|
||||
}
|
||||
12
src/.vs/VSWorkspaceState.json
Normal file
12
src/.vs/VSWorkspaceState.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"OutputFoldersPerTargetSystem": {
|
||||
"Local Machine": [
|
||||
"out\\build\\x64-Debug",
|
||||
"out\\install\\x64-Debug"
|
||||
]
|
||||
},
|
||||
"ExpandedNodes": [
|
||||
""
|
||||
],
|
||||
"PreviewInSolutionExplorer": false
|
||||
}
|
||||
BIN
src/.vs/slnx.sqlite
Normal file
BIN
src/.vs/slnx.sqlite
Normal file
Binary file not shown.
BIN
src/.vs/src/CopilotIndices/17.14.1091.29919/CodeChunks.db
Normal file
BIN
src/.vs/src/CopilotIndices/17.14.1091.29919/CodeChunks.db
Normal file
Binary file not shown.
BIN
src/.vs/src/CopilotIndices/17.14.1091.29919/SemanticSymbols.db
Normal file
BIN
src/.vs/src/CopilotIndices/17.14.1091.29919/SemanticSymbols.db
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
src/.vs/src/v17/.wsuo
Normal file
BIN
src/.vs/src/v17/.wsuo
Normal file
Binary file not shown.
BIN
src/.vs/src/v17/Browse.VC.db
Normal file
BIN
src/.vs/src/v17/Browse.VC.db
Normal file
Binary file not shown.
61
src/.vs/src/v17/DocumentLayout.json
Normal file
61
src/.vs/src/v17/DocumentLayout.json
Normal file
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"Version": 1,
|
||||
"WorkspaceRootPath": "D:\\msys64\\home\\dompp\\86Box\\src\\",
|
||||
"Documents": [
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|D:\\msys64\\home\\dompp\\86Box\\src\\CMakeSettings.json||{10608CD5-279C-4A28-BD5F-BA2CFCE06219}",
|
||||
"RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:CMakeSettings.json||{10608CD5-279C-4A28-BD5F-BA2CFCE06219}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|CMake Overview Pages||{B1CAA5B0-FEB1-4350-8AB9-F895876842F2}"
|
||||
}
|
||||
],
|
||||
"DocumentGroupContainers": [
|
||||
{
|
||||
"Orientation": 0,
|
||||
"VerticalTabListWidth": 256,
|
||||
"DocumentGroups": [
|
||||
{
|
||||
"DockedWidth": 200,
|
||||
"SelectedChildIndex": 3,
|
||||
"Children": [
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{65ddf8c3-8f89-4077-a6c6-dbb8853aab13}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:11:0:{2456bd12-ecf7-4988-a4a6-67d49173f565}"
|
||||
},
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:12:0:{2456bd12-ecf7-4988-a4a6-67d49173f565}"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 0,
|
||||
"Title": "CMakeSettings.json",
|
||||
"DocumentMoniker": "D:\\msys64\\home\\dompp\\86Box\\src\\CMakeSettings.json",
|
||||
"RelativeDocumentMoniker": "CMakeSettings.json",
|
||||
"ToolTip": "D:\\msys64\\home\\dompp\\86Box\\src\\CMakeSettings.json",
|
||||
"RelativeToolTip": "CMakeSettings.json",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|",
|
||||
"WhenOpened": "2025-08-30T19:09:23.796Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 1,
|
||||
"Title": "CMake Overview Pages",
|
||||
"DocumentMoniker": "CMake Overview Pages",
|
||||
"ToolTip": "CMake Overview Pages",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|",
|
||||
"WhenOpened": "2025-08-30T19:09:12.336Z",
|
||||
"EditorCaption": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
src/.vs/src/v17/workspaceFileList.bin
Normal file
BIN
src/.vs/src/v17/workspaceFileList.bin
Normal file
Binary file not shown.
15
src/CMakeSettings.json
Normal file
15
src/CMakeSettings.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "x64-Debug",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Debug",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -10,9 +10,12 @@
|
||||
#
|
||||
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
# Jasmine Iwanek, <jriwanek@gmail.com>
|
||||
# Toni Riikonen, <riikonen.toni@gmail.com>
|
||||
#
|
||||
# Copyright 2020-2021 David Hrdlička.
|
||||
# Copyright 2024 Jasmine Iwanek.
|
||||
# Copyright 2025 Toni Riikonen.
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
add_library(fdd OBJECT
|
||||
@@ -31,6 +34,7 @@ add_library(fdd OBJECT
|
||||
fdd_pcjs.c
|
||||
fdd_mfm.c
|
||||
fdd_td0.c
|
||||
fdd_audio.c
|
||||
)
|
||||
|
||||
add_subdirectory(lzw)
|
||||
|
||||
140
src/floppy/fdd.c
140
src/floppy/fdd.c
@@ -23,6 +23,8 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/timer.h>
|
||||
@@ -39,6 +41,7 @@
|
||||
#include <86box/fdd_mfm.h>
|
||||
#include <86box/fdd_td0.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/fdd_audio.h>
|
||||
|
||||
/* Flags:
|
||||
Bit 0: 300 rpm supported;
|
||||
@@ -88,7 +91,7 @@ int writeprot[FDD_NUM];
|
||||
int fwriteprot[FDD_NUM];
|
||||
int fdd_changed[FDD_NUM];
|
||||
int ui_writeprot[FDD_NUM] = { 0, 0, 0, 0 };
|
||||
int drive_empty[FDD_NUM] = { 1, 1, 1, 1 };
|
||||
int drive_empty[FDD_NUM] = { 1, 1, 1, 1 };
|
||||
|
||||
DRIVE drives[FDD_NUM];
|
||||
|
||||
@@ -101,43 +104,43 @@ d86f_handler_t d86f_handler[FDD_NUM];
|
||||
static const struct
|
||||
{
|
||||
const char *ext;
|
||||
void (*load)(int drive, char *fn);
|
||||
void (*close)(int drive);
|
||||
int size;
|
||||
void (*load)(int drive, char *fn);
|
||||
void (*close)(int drive);
|
||||
int size;
|
||||
} loaders[] = {
|
||||
{ "001", img_load, img_close, -1},
|
||||
{ "002", img_load, img_close, -1},
|
||||
{ "003", img_load, img_close, -1},
|
||||
{ "004", img_load, img_close, -1},
|
||||
{ "005", img_load, img_close, -1},
|
||||
{ "006", img_load, img_close, -1},
|
||||
{ "007", img_load, img_close, -1},
|
||||
{ "008", img_load, img_close, -1},
|
||||
{ "009", img_load, img_close, -1},
|
||||
{ "010", img_load, img_close, -1},
|
||||
{ "12", img_load, img_close, -1},
|
||||
{ "144", img_load, img_close, -1},
|
||||
{ "360", img_load, img_close, -1},
|
||||
{ "720", img_load, img_close, -1},
|
||||
{ "86F", d86f_load, d86f_close, -1},
|
||||
{ "BIN", img_load, img_close, -1},
|
||||
{ "CQ", img_load, img_close, -1},
|
||||
{ "CQM", img_load, img_close, -1},
|
||||
{ "DDI", img_load, img_close, -1},
|
||||
{ "DSK", img_load, img_close, -1},
|
||||
{ "FDI", fdi_load, fdi_close, -1},
|
||||
{ "FDF", img_load, img_close, -1},
|
||||
{ "FLP", img_load, img_close, -1},
|
||||
{ "HDM", img_load, img_close, -1},
|
||||
{ "IMA", img_load, img_close, -1},
|
||||
{ "IMD", imd_load, imd_close, -1},
|
||||
{ "IMG", img_load, img_close, -1},
|
||||
{ "JSON", pcjs_load, pcjs_close, -1},
|
||||
{ "MFM", mfm_load, mfm_close, -1},
|
||||
{ "TD0", td0_load, td0_close, -1},
|
||||
{ "VFD", img_load, img_close, -1},
|
||||
{ "XDF", img_load, img_close, -1},
|
||||
{ 0, 0, 0, 0 }
|
||||
{ "001", img_load, img_close, -1 },
|
||||
{ "002", img_load, img_close, -1 },
|
||||
{ "003", img_load, img_close, -1 },
|
||||
{ "004", img_load, img_close, -1 },
|
||||
{ "005", img_load, img_close, -1 },
|
||||
{ "006", img_load, img_close, -1 },
|
||||
{ "007", img_load, img_close, -1 },
|
||||
{ "008", img_load, img_close, -1 },
|
||||
{ "009", img_load, img_close, -1 },
|
||||
{ "010", img_load, img_close, -1 },
|
||||
{ "12", img_load, img_close, -1 },
|
||||
{ "144", img_load, img_close, -1 },
|
||||
{ "360", img_load, img_close, -1 },
|
||||
{ "720", img_load, img_close, -1 },
|
||||
{ "86F", d86f_load, d86f_close, -1 },
|
||||
{ "BIN", img_load, img_close, -1 },
|
||||
{ "CQ", img_load, img_close, -1 },
|
||||
{ "CQM", img_load, img_close, -1 },
|
||||
{ "DDI", img_load, img_close, -1 },
|
||||
{ "DSK", img_load, img_close, -1 },
|
||||
{ "FDI", fdi_load, fdi_close, -1 },
|
||||
{ "FDF", img_load, img_close, -1 },
|
||||
{ "FLP", img_load, img_close, -1 },
|
||||
{ "HDM", img_load, img_close, -1 },
|
||||
{ "IMA", img_load, img_close, -1 },
|
||||
{ "IMD", imd_load, imd_close, -1 },
|
||||
{ "IMG", img_load, img_close, -1 },
|
||||
{ "JSON", pcjs_load, pcjs_close, -1 },
|
||||
{ "MFM", mfm_load, mfm_close, -1 },
|
||||
{ "TD0", td0_load, td0_close, -1 },
|
||||
{ "VFD", img_load, img_close, -1 },
|
||||
{ "XDF", img_load, img_close, -1 },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static const struct {
|
||||
@@ -147,35 +150,35 @@ static const struct {
|
||||
const char *internal_name;
|
||||
} drive_types[] = {
|
||||
/* None */
|
||||
{ 0, 0, "None", "none" },
|
||||
{ 0, 0, "None", "none" },
|
||||
/* 5.25" 1DD */
|
||||
{ 43, FLAG_RPM_300 | FLAG_525 | FLAG_HOLE0, "5.25\" 180k", "525_1dd" },
|
||||
{ 43, FLAG_RPM_300 | FLAG_525 | FLAG_HOLE0, "5.25\" 180k", "525_1dd" },
|
||||
/* 5.25" DD */
|
||||
{ 43, FLAG_RPM_300 | FLAG_525 | FLAG_DS | FLAG_HOLE0, "5.25\" 360k", "525_2dd" },
|
||||
{ 43, FLAG_RPM_300 | FLAG_525 | FLAG_DS | FLAG_HOLE0, "5.25\" 360k", "525_2dd" },
|
||||
/* 5.25" QD */
|
||||
{ 86, FLAG_RPM_300 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_DOUBLE_STEP, "5.25\" 720k", "525_2qd" },
|
||||
{ 86, FLAG_RPM_300 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_DOUBLE_STEP, "5.25\" 720k", "525_2qd" },
|
||||
/* 5.25" HD */
|
||||
{ 86, FLAG_RPM_360 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_PS2, "5.25\" 1.2M", "525_2hd" },
|
||||
{ 86, FLAG_RPM_360 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_PS2, "5.25\" 1.2M", "525_2hd" },
|
||||
/* 5.25" HD Dual RPM */
|
||||
{ 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "5.25\" 1.2M 300/360 RPM", "525_2hd_dualrpm" },
|
||||
{ 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "5.25\" 1.2M 300/360 RPM", "525_2hd_dualrpm" },
|
||||
/* 3.5" 1DD */
|
||||
{ 86, FLAG_RPM_300 | FLAG_HOLE0 | FLAG_DOUBLE_STEP, "3.5\" 360k", "35_1dd" },
|
||||
{ 86, FLAG_RPM_300 | FLAG_HOLE0 | FLAG_DOUBLE_STEP, "3.5\" 360k", "35_1dd" },
|
||||
/* 3.5" DD, Equivalent to TEAC FD-235F */
|
||||
{ 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_DOUBLE_STEP, "3.5\" 720k", "35_2dd" },
|
||||
{ 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_DOUBLE_STEP, "3.5\" 720k", "35_2dd" },
|
||||
/* 3.5" HD, Equivalent to TEAC FD-235HF */
|
||||
{ 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_PS2, "3.5\" 1.44M", "35_2hd" },
|
||||
{ 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_PS2, "3.5\" 1.44M", "35_2hd" },
|
||||
/* TODO: 3.5" DD, Equivalent to TEAC FD-235GF */
|
||||
// { 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "3.5\" 1.25M", "35_2hd_2mode" },
|
||||
// { 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "3.5\" 1.25M", "35_2hd_2mode" },
|
||||
/* 3.5" HD PC-98 */
|
||||
{ 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_INVERT_DENSEL, "3.5\" 1.25M PC-98", "35_2hd_nec" },
|
||||
{ 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_INVERT_DENSEL, "3.5\" 1.25M PC-98", "35_2hd_nec" },
|
||||
/* 3.5" HD 3-Mode, Equivalent to TEAC FD-235HG */
|
||||
{ 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "3.5\" 1.44M 300/360 RPM", "35_2hd_3mode" },
|
||||
{ 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "3.5\" 1.44M 300/360 RPM", "35_2hd_3mode" },
|
||||
/* 3.5" ED, Equivalent to TEAC FD-235J */
|
||||
{ 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_HOLE2 | FLAG_DOUBLE_STEP, "3.5\" 2.88M", "35_2ed" },
|
||||
{ 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_HOLE2 | FLAG_DOUBLE_STEP, "3.5\" 2.88M", "35_2ed" },
|
||||
/* 3.5" ED Dual RPM, Equivalent to TEAC FD-335J */
|
||||
{ 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_HOLE2 | FLAG_DOUBLE_STEP, "3.5\" 2.88M 300/360 RPM", "35_2ed_dualrpm" },
|
||||
{ 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_HOLE2 | FLAG_DOUBLE_STEP, "3.5\" 2.88M 300/360 RPM", "35_2ed_dualrpm" },
|
||||
/* End of list */
|
||||
{ -1, -1, "", "" }
|
||||
{ -1, -1, "", "" }
|
||||
};
|
||||
|
||||
#ifdef ENABLE_FDD_LOG
|
||||
@@ -211,7 +214,7 @@ fdd_get_internal_name(int type)
|
||||
int
|
||||
fdd_get_from_internal_name(char *s)
|
||||
{
|
||||
int c = 0;
|
||||
int c = 0;
|
||||
|
||||
while (strlen(drive_types[c].internal_name)) {
|
||||
if (!strcmp((char *) drive_types[c].internal_name, s))
|
||||
@@ -250,6 +253,8 @@ fdd_seek(int drive, int track_diff)
|
||||
if (!track_diff)
|
||||
return;
|
||||
|
||||
int old_track = fdd[drive].track;
|
||||
|
||||
fdd[drive].track += track_diff;
|
||||
|
||||
if (fdd[drive].track < 0)
|
||||
@@ -260,6 +265,16 @@ fdd_seek(int drive, int track_diff)
|
||||
|
||||
fdd_changed[drive] = 0;
|
||||
|
||||
/* Trigger appropriate audio for track movements */
|
||||
int actual_track_diff = abs(old_track - fdd[drive].track);
|
||||
if (actual_track_diff == 1) {
|
||||
/* Single track movement */
|
||||
fdd_audio_play_single_track_step(drive, old_track, fdd[drive].track);
|
||||
} else if (actual_track_diff > 1) {
|
||||
/* Multi-track seek */
|
||||
fdd_audio_play_multi_track_seek(drive, old_track, fdd[drive].track);
|
||||
}
|
||||
|
||||
fdd_do_seek(drive, fdd[drive].track);
|
||||
}
|
||||
|
||||
@@ -461,12 +476,10 @@ fdd_load(int drive, char *fn)
|
||||
FILE *fp;
|
||||
int offs = 0;
|
||||
|
||||
fdd_log("FDD: loading drive %d with '%s'\n", drive, fn);
|
||||
|
||||
if (!fn)
|
||||
return;
|
||||
if (strstr(fn, "wp://") == fn) {
|
||||
offs = 5;
|
||||
offs = 5;
|
||||
ui_writeprot[drive] = 1;
|
||||
}
|
||||
fn += offs;
|
||||
@@ -495,7 +508,6 @@ fdd_load(int drive, char *fn)
|
||||
c++;
|
||||
}
|
||||
}
|
||||
fdd_log("FDD: could not load '%s' %s\n", fn, p);
|
||||
drive_empty[drive] = 1;
|
||||
fdd_set_head(drive, 0);
|
||||
memset(floppyfns[drive], 0, sizeof(floppyfns[drive]));
|
||||
@@ -505,8 +517,6 @@ fdd_load(int drive, char *fn)
|
||||
void
|
||||
fdd_close(int drive)
|
||||
{
|
||||
fdd_log("FDD: closing drive %d\n", drive);
|
||||
|
||||
d86f_stop(drive); /* Call this first of all to make sure the 86F poll is back to idle state. */
|
||||
if (loaders[driveloaders[drive]].close)
|
||||
loaders[driveloaders[drive]].close(drive);
|
||||
@@ -548,11 +558,13 @@ fdd_byteperiod(int drive)
|
||||
void
|
||||
fdd_set_motor_enable(int drive, int motor_enable)
|
||||
{
|
||||
/* I think here is where spin-up and spin-down should be implemented. */
|
||||
if (motor_enable && !motoron[drive])
|
||||
fdd_audio_set_motor_enable(drive, motor_enable);
|
||||
|
||||
if (motor_enable && !motoron[drive]) {
|
||||
timer_set_delay_u64(&fdd_poll_time[drive], fdd_byteperiod(drive));
|
||||
else if (!motor_enable)
|
||||
} else if (!motor_enable && motoron[drive]) {
|
||||
timer_disable(&fdd_poll_time[drive]);
|
||||
}
|
||||
motoron[drive] = motor_enable;
|
||||
}
|
||||
|
||||
@@ -690,10 +702,12 @@ fdd_init(void)
|
||||
for (i = 0; i < FDD_NUM; i++) {
|
||||
fdd_load(i, floppyfns[i]);
|
||||
}
|
||||
|
||||
fdd_audio_init();
|
||||
}
|
||||
|
||||
void
|
||||
fdd_do_writeback(int drive)
|
||||
{
|
||||
d86f_handler[drive].writeback(drive);
|
||||
}
|
||||
}
|
||||
492
src/floppy/fdd_audio.c
Normal file
492
src/floppy/fdd_audio.c
Normal file
@@ -0,0 +1,492 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the floppy drive audio emulation.
|
||||
*
|
||||
* Authors: Toni Riikonen, <riikonen.toni@gmail.com>
|
||||
*
|
||||
* Copyright 2025 Toni Riikonen.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdd_audio.h>
|
||||
#include <86box/sound.h>
|
||||
|
||||
// TODO:
|
||||
// OK 1. Implement spindle motor spin-up and spin-down
|
||||
// OK 2. Move audio emulation to separate code file
|
||||
// OK 3. Implement sound support for all drives (not only for drive 0)
|
||||
// OK 4. Single sector read/write sound emulation
|
||||
// OK 5. Multi-track seek sound emulation
|
||||
// 6. Limit sound emulation only for 3,5" 300 rpm drives, until we have sound samples for other rpm drives
|
||||
// 7. Volume control for drive sounds
|
||||
// 8. Configuration option to enable/disable drive sounds
|
||||
|
||||
/* Audio sample structure */
|
||||
typedef struct {
|
||||
const char *filename;
|
||||
int16_t *buffer;
|
||||
int samples;
|
||||
} audio_sample_t;
|
||||
|
||||
/* Single step audio state */
|
||||
typedef struct {
|
||||
int position;
|
||||
int active;
|
||||
} single_step_state_t;
|
||||
|
||||
/* Multi-track seek audio state */
|
||||
typedef struct {
|
||||
int position;
|
||||
int active;
|
||||
int duration_samples;
|
||||
int from_track;
|
||||
int to_track;
|
||||
} multi_seek_state_t;
|
||||
|
||||
/* Static audio sample definitions */
|
||||
static audio_sample_t spindlemotor_start = {
|
||||
.filename = "mitsumi_spindle_motor_start_48000_16_1_PCM.wav",
|
||||
.buffer = NULL,
|
||||
.samples = 0
|
||||
};
|
||||
|
||||
static audio_sample_t spindlemotor_loop = {
|
||||
.filename = "mitsumi_spindle_motor_loop_48000_16_1_PCM.wav",
|
||||
.buffer = NULL,
|
||||
.samples = 0
|
||||
};
|
||||
|
||||
static audio_sample_t spindlemotor_stop = {
|
||||
.filename = "mitsumi_spindle_motor_stop_48000_16_1_PCM.wav",
|
||||
.buffer = NULL,
|
||||
.samples = 0
|
||||
};
|
||||
|
||||
static audio_sample_t single_track_step = {
|
||||
.filename = "mitsumi_track_step_48000_16_1_PCM.wav",
|
||||
.buffer = NULL,
|
||||
.samples = 0
|
||||
};
|
||||
|
||||
static audio_sample_t multi_track_seek = {
|
||||
.filename = "mitsumi_seek_80_tracks_495ms_48000_16_1_PCM.wav",
|
||||
.buffer = NULL,
|
||||
.samples = 0
|
||||
};
|
||||
|
||||
/* Audio state for each drive */
|
||||
static int spindlemotor_pos[FDD_NUM] = {};
|
||||
static motor_state_t spindlemotor_state[FDD_NUM] = {};
|
||||
static float spindlemotor_fade_volume[FDD_NUM] = {};
|
||||
static int spindlemotor_fade_samples_remaining[FDD_NUM] = {};
|
||||
|
||||
/* Single step audio state for each drive */
|
||||
static single_step_state_t single_step_state[FDD_NUM] = {};
|
||||
|
||||
/* Multi-track seek audio state for each drive */
|
||||
static multi_seek_state_t multi_seek_state[FDD_NUM] = {};
|
||||
|
||||
extern uint64_t motoron[FDD_NUM];
|
||||
|
||||
/* Forward declaration */
|
||||
static int16_t *load_wav(const char *filename, int *sample_count);
|
||||
|
||||
const char *
|
||||
fdd_audio_motor_state_name(motor_state_t state)
|
||||
{
|
||||
switch (state) {
|
||||
case MOTOR_STATE_STOPPED:
|
||||
return "STOPPED";
|
||||
case MOTOR_STATE_STARTING:
|
||||
return "STARTING";
|
||||
case MOTOR_STATE_RUNNING:
|
||||
return "RUNNING";
|
||||
case MOTOR_STATE_STOPPING:
|
||||
return "STOPPING";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static int16_t *
|
||||
load_wav(const char *filename, int *sample_count)
|
||||
{
|
||||
FILE *f = fopen(filename, "rb");
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
wav_header_t hdr;
|
||||
if (fread(&hdr, sizeof(hdr), 1, f) != 1) {
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (memcmp(hdr.riff, "RIFF", 4) || memcmp(hdr.wave, "WAVE", 4) || memcmp(hdr.fmt, "fmt ", 4) || memcmp(hdr.data, "data", 4)) {
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Accept both mono and stereo, 16-bit PCM */
|
||||
if (hdr.audio_format != 1 || hdr.bits_per_sample != 16 || (hdr.num_channels != 1 && hdr.num_channels != 2)) {
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int input_samples = hdr.data_size / 2; /* 2 bytes per sample */
|
||||
int16_t *input_data = malloc(hdr.data_size);
|
||||
if (!input_data) {
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fread(input_data, 1, hdr.data_size, f) != hdr.data_size) {
|
||||
free(input_data);
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
int16_t *output_data;
|
||||
int output_samples;
|
||||
|
||||
if (hdr.num_channels == 1) {
|
||||
/* Convert mono to stereo */
|
||||
output_samples = input_samples; /* Number of stereo sample pairs */
|
||||
output_data = malloc(input_samples * 2 * sizeof(int16_t)); /* Allocate for stereo */
|
||||
if (!output_data) {
|
||||
free(input_data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Convert mono to stereo by duplicating each sample */
|
||||
for (int i = 0; i < input_samples; i++) {
|
||||
output_data[i * 2] = input_data[i]; /* Left channel */
|
||||
output_data[i * 2 + 1] = input_data[i]; /* Right channel */
|
||||
}
|
||||
|
||||
free(input_data);
|
||||
} else {
|
||||
/* Already stereo */
|
||||
output_data = input_data;
|
||||
output_samples = input_samples / 2; /* Number of stereo sample pairs */
|
||||
}
|
||||
|
||||
if (sample_count)
|
||||
*sample_count = output_samples;
|
||||
|
||||
return output_data;
|
||||
}
|
||||
|
||||
void
|
||||
fdd_audio_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Load audio samples using the new structure */
|
||||
spindlemotor_start.buffer = load_wav(spindlemotor_start.filename, &spindlemotor_start.samples);
|
||||
spindlemotor_loop.buffer = load_wav(spindlemotor_loop.filename, &spindlemotor_loop.samples);
|
||||
spindlemotor_stop.buffer = load_wav(spindlemotor_stop.filename, &spindlemotor_stop.samples);
|
||||
single_track_step.buffer = load_wav(single_track_step.filename, &single_track_step.samples);
|
||||
multi_track_seek.buffer = load_wav(multi_track_seek.filename, &multi_track_seek.samples);
|
||||
|
||||
/* Initialize audio state for all drives */
|
||||
for (i = 0; i < FDD_NUM; i++) {
|
||||
spindlemotor_pos[i] = 0;
|
||||
spindlemotor_state[i] = MOTOR_STATE_STOPPED;
|
||||
spindlemotor_fade_volume[i] = 1.0f;
|
||||
spindlemotor_fade_samples_remaining[i] = 0;
|
||||
|
||||
/* Initialize single step state */
|
||||
single_step_state[i].position = 0;
|
||||
single_step_state[i].active = 0;
|
||||
|
||||
/* Initialize multi-track seek state */
|
||||
multi_seek_state[i].position = 0;
|
||||
multi_seek_state[i].active = 0;
|
||||
multi_seek_state[i].duration_samples = 0;
|
||||
multi_seek_state[i].from_track = -1;
|
||||
multi_seek_state[i].to_track = -1;
|
||||
}
|
||||
|
||||
/* Initialize sound thread */
|
||||
sound_fdd_thread_init();
|
||||
}
|
||||
|
||||
void
|
||||
fdd_audio_close(void)
|
||||
{
|
||||
if (spindlemotor_start.buffer) {
|
||||
free(spindlemotor_start.buffer);
|
||||
spindlemotor_start.buffer = NULL;
|
||||
spindlemotor_start.samples = 0;
|
||||
}
|
||||
if (spindlemotor_loop.buffer) {
|
||||
free(spindlemotor_loop.buffer);
|
||||
spindlemotor_loop.buffer = NULL;
|
||||
spindlemotor_loop.samples = 0;
|
||||
}
|
||||
if (spindlemotor_stop.buffer) {
|
||||
free(spindlemotor_stop.buffer);
|
||||
spindlemotor_stop.buffer = NULL;
|
||||
spindlemotor_stop.samples = 0;
|
||||
}
|
||||
if (single_track_step.buffer) {
|
||||
free(single_track_step.buffer);
|
||||
single_track_step.buffer = NULL;
|
||||
single_track_step.samples = 0;
|
||||
}
|
||||
if (multi_track_seek.buffer) {
|
||||
free(multi_track_seek.buffer);
|
||||
multi_track_seek.buffer = NULL;
|
||||
multi_track_seek.samples = 0;
|
||||
}
|
||||
|
||||
/* End sound thread */
|
||||
sound_fdd_thread_end();
|
||||
}
|
||||
|
||||
void
|
||||
fdd_audio_set_motor_enable(int drive, int motor_enable)
|
||||
{
|
||||
if (motor_enable && !motoron[drive]) {
|
||||
/* Motor starting up */
|
||||
if (spindlemotor_state[drive] == MOTOR_STATE_STOPPING) {
|
||||
/* Interrupt stop sequence and transition back to loop */
|
||||
spindlemotor_state[drive] = MOTOR_STATE_RUNNING;
|
||||
spindlemotor_pos[drive] = 0;
|
||||
spindlemotor_fade_volume[drive] = 1.0f;
|
||||
spindlemotor_fade_samples_remaining[drive] = 0;
|
||||
} else {
|
||||
/* Normal startup */
|
||||
spindlemotor_state[drive] = MOTOR_STATE_STARTING;
|
||||
spindlemotor_pos[drive] = 0;
|
||||
spindlemotor_fade_volume[drive] = 1.0f;
|
||||
spindlemotor_fade_samples_remaining[drive] = 0;
|
||||
}
|
||||
} else if (!motor_enable && motoron[drive]) {
|
||||
/* Motor stopping */
|
||||
spindlemotor_state[drive] = MOTOR_STATE_STOPPING;
|
||||
spindlemotor_pos[drive] = 0;
|
||||
spindlemotor_fade_volume[drive] = 1.0f;
|
||||
spindlemotor_fade_samples_remaining[drive] = FADE_SAMPLES;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fdd_audio_play_single_track_step(int drive, int from_track, int to_track)
|
||||
{
|
||||
if (drive < 0 || drive >= FDD_NUM)
|
||||
return;
|
||||
if (abs(from_track - to_track) != 1)
|
||||
return; /* Only single track movements */
|
||||
|
||||
single_step_state[drive].position = 0;
|
||||
single_step_state[drive].active = 1;
|
||||
}
|
||||
|
||||
void
|
||||
fdd_audio_play_multi_track_seek(int drive, int from_track, int to_track)
|
||||
{
|
||||
if (drive < 0 || drive >= FDD_NUM)
|
||||
return;
|
||||
|
||||
int track_diff = abs(from_track - to_track);
|
||||
if (track_diff <= 1)
|
||||
return; /* Use single step for 1 track movements */
|
||||
|
||||
if (!multi_track_seek.buffer || multi_track_seek.samples == 0)
|
||||
return; /* No multi-track seek sample loaded */
|
||||
|
||||
/* Check if a seek is already active */
|
||||
if (multi_seek_state[drive].active &&
|
||||
multi_seek_state[drive].from_track == from_track &&
|
||||
multi_seek_state[drive].to_track == to_track) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Calculate duration: 495ms for 80 tracks = 6.1875ms per track at 48kHz sample rate */
|
||||
/* 6.1875ms = 0.0061875s, at 48000 Hz = 297 samples per track */
|
||||
int duration_samples = track_diff * 297; /* 6.1875ms * track_diff * 48kHz */
|
||||
|
||||
/* Clamp to maximum available sample length */
|
||||
if (duration_samples > multi_track_seek.samples)
|
||||
duration_samples = multi_track_seek.samples;
|
||||
|
||||
/* Start new seek (or restart interrupted seek) */
|
||||
multi_seek_state[drive].position = 0;
|
||||
multi_seek_state[drive].active = 1;
|
||||
multi_seek_state[drive].duration_samples = duration_samples;
|
||||
multi_seek_state[drive].from_track = from_track;
|
||||
multi_seek_state[drive].to_track = to_track;
|
||||
}
|
||||
|
||||
void
|
||||
fdd_audio_callback(int16_t *buffer, int length)
|
||||
{
|
||||
/* Clear buffer */
|
||||
memset(buffer, 0, length * sizeof(int16_t));
|
||||
|
||||
/* Check if any motor is running or transitioning, or any audio is active */
|
||||
int any_audio_active = 0;
|
||||
for (int drive = 0; drive < FDD_NUM; drive++) {
|
||||
if (spindlemotor_state[drive] != MOTOR_STATE_STOPPED ||
|
||||
single_step_state[drive].active ||
|
||||
multi_seek_state[drive].active) {
|
||||
any_audio_active = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!any_audio_active)
|
||||
return;
|
||||
|
||||
float *float_buffer = (float *) buffer;
|
||||
int samples_in_buffer = length / 2;
|
||||
|
||||
/* Process audio for all drives */
|
||||
for (int drive = 0; drive < FDD_NUM; drive++) {
|
||||
for (int i = 0; i < samples_in_buffer; i++) {
|
||||
float left_sample = 0.0f;
|
||||
float right_sample = 0.0f;
|
||||
|
||||
/* Process motor audio */
|
||||
if (spindlemotor_state[drive] != MOTOR_STATE_STOPPED) {
|
||||
switch (spindlemotor_state[drive]) {
|
||||
case MOTOR_STATE_STARTING:
|
||||
if (spindlemotor_start.buffer && spindlemotor_pos[drive] < spindlemotor_start.samples) {
|
||||
/* Play start sound */
|
||||
left_sample = (float) spindlemotor_start.buffer[spindlemotor_pos[drive] * 2] / 32768.0f;
|
||||
right_sample = (float) spindlemotor_start.buffer[spindlemotor_pos[drive] * 2 + 1] / 32768.0f;
|
||||
spindlemotor_pos[drive]++;
|
||||
} else {
|
||||
/* Start sound finished, transition to loop */
|
||||
spindlemotor_state[drive] = MOTOR_STATE_RUNNING;
|
||||
spindlemotor_pos[drive] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case MOTOR_STATE_RUNNING:
|
||||
if (spindlemotor_loop.buffer && spindlemotor_loop.samples > 0) {
|
||||
/* Play loop sound */
|
||||
left_sample = (float) spindlemotor_loop.buffer[spindlemotor_pos[drive] * 2] / 32768.0f;
|
||||
right_sample = (float) spindlemotor_loop.buffer[spindlemotor_pos[drive] * 2 + 1] / 32768.0f;
|
||||
spindlemotor_pos[drive]++;
|
||||
|
||||
/* Loop back to beginning */
|
||||
if (spindlemotor_pos[drive] >= spindlemotor_loop.samples) {
|
||||
spindlemotor_pos[drive] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MOTOR_STATE_STOPPING:
|
||||
if (spindlemotor_fade_samples_remaining[drive] > 0) {
|
||||
/* Mix fading loop sound with rising stop sound */
|
||||
float loop_volume = spindlemotor_fade_volume[drive];
|
||||
float stop_volume = 1.0f - loop_volume;
|
||||
|
||||
float loop_left = 0.0f, loop_right = 0.0f;
|
||||
float stop_left = 0.0f, stop_right = 0.0f;
|
||||
|
||||
/* Get loop sample (continue from current position) */
|
||||
if (spindlemotor_loop.buffer && spindlemotor_loop.samples > 0) {
|
||||
int loop_pos = spindlemotor_pos[drive] % spindlemotor_loop.samples;
|
||||
loop_left = (float) spindlemotor_loop.buffer[loop_pos * 2] / 32768.0f;
|
||||
loop_right = (float) spindlemotor_loop.buffer[loop_pos * 2 + 1] / 32768.0f;
|
||||
}
|
||||
|
||||
/* Get stop sample */
|
||||
if (spindlemotor_stop.buffer && spindlemotor_pos[drive] < spindlemotor_stop.samples) {
|
||||
stop_left = (float) spindlemotor_stop.buffer[spindlemotor_pos[drive] * 2] / 32768.0f;
|
||||
stop_right = (float) spindlemotor_stop.buffer[spindlemotor_pos[drive] * 2 + 1] / 32768.0f;
|
||||
}
|
||||
|
||||
/* Mix the sounds */
|
||||
left_sample = loop_left * loop_volume + stop_left * stop_volume;
|
||||
right_sample = loop_right * loop_volume + stop_right * stop_volume;
|
||||
|
||||
spindlemotor_pos[drive]++;
|
||||
spindlemotor_fade_samples_remaining[drive]--;
|
||||
|
||||
/* Update fade volume */
|
||||
spindlemotor_fade_volume[drive] = (float) spindlemotor_fade_samples_remaining[drive] / FADE_SAMPLES;
|
||||
} else {
|
||||
/* Fade completed, play remaining stop sound */
|
||||
if (spindlemotor_stop.buffer && spindlemotor_pos[drive] < spindlemotor_stop.samples) {
|
||||
left_sample = (float) spindlemotor_stop.buffer[spindlemotor_pos[drive] * 2] / 32768.0f;
|
||||
right_sample = (float) spindlemotor_stop.buffer[spindlemotor_pos[drive] * 2 + 1] / 32768.0f;
|
||||
spindlemotor_pos[drive]++;
|
||||
} else {
|
||||
/* Stop sound finished */
|
||||
spindlemotor_state[drive] = MOTOR_STATE_STOPPED;
|
||||
/* Note: Timer disabling is handled by fdd.c, not here */
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Process single step audio */
|
||||
if (single_step_state[drive].active) {
|
||||
if (single_track_step.buffer && single_step_state[drive].position < single_track_step.samples) {
|
||||
/* Mix step sound with motor sound */
|
||||
float step_left = (float) single_track_step.buffer[single_step_state[drive].position * 2] / 32768.0f;
|
||||
float step_right = (float) single_track_step.buffer[single_step_state[drive].position * 2 + 1] / 32768.0f;
|
||||
|
||||
left_sample += step_left;
|
||||
right_sample += step_right;
|
||||
|
||||
single_step_state[drive].position++;
|
||||
} else {
|
||||
/* Step sound finished */
|
||||
single_step_state[drive].active = 0;
|
||||
single_step_state[drive].position = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Process multi-track seek audio */
|
||||
if (multi_seek_state[drive].active) {
|
||||
if (multi_track_seek.buffer &&
|
||||
multi_seek_state[drive].position < multi_seek_state[drive].duration_samples &&
|
||||
multi_seek_state[drive].position < multi_track_seek.samples) {
|
||||
/* Mix seek sound with motor sound */
|
||||
float seek_left = (float) multi_track_seek.buffer[multi_seek_state[drive].position * 2] / 32768.0f;
|
||||
float seek_right = (float) multi_track_seek.buffer[multi_seek_state[drive].position * 2 + 1] / 32768.0f;
|
||||
|
||||
left_sample += seek_left;
|
||||
right_sample += seek_right;
|
||||
|
||||
multi_seek_state[drive].position++;
|
||||
} else {
|
||||
/* Seek sound finished */
|
||||
multi_seek_state[drive].active = 0;
|
||||
multi_seek_state[drive].position = 0;
|
||||
multi_seek_state[drive].duration_samples = 0;
|
||||
multi_seek_state[drive].from_track = -1;
|
||||
multi_seek_state[drive].to_track = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mix this drive's audio into the buffer */
|
||||
float_buffer[i * 2] += left_sample;
|
||||
float_buffer[i * 2 + 1] += right_sample;
|
||||
}
|
||||
}
|
||||
}
|
||||
76
src/include/86box/fdd_audio.h
Normal file
76
src/include/86box/fdd_audio.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Definitions for the floppy drive audio emulation.
|
||||
*
|
||||
* Authors: Toni Riikonen, <riikonen.toni@gmail.com>
|
||||
*
|
||||
* Copyright 2025 Toni Riikonen.
|
||||
*/
|
||||
#ifndef EMU_FDD_AUDIO_H
|
||||
#define EMU_FDD_AUDIO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Motor sound states */
|
||||
typedef enum {
|
||||
MOTOR_STATE_STOPPED = 0,
|
||||
MOTOR_STATE_STARTING,
|
||||
MOTOR_STATE_RUNNING,
|
||||
MOTOR_STATE_STOPPING
|
||||
} motor_state_t;
|
||||
|
||||
/* WAV header structure */
|
||||
typedef struct {
|
||||
char riff[4];
|
||||
uint32_t size;
|
||||
char wave[4];
|
||||
char fmt[4];
|
||||
uint32_t fmt_size;
|
||||
uint16_t audio_format;
|
||||
uint16_t num_channels;
|
||||
uint32_t sample_rate;
|
||||
uint32_t byte_rate;
|
||||
uint16_t block_align;
|
||||
uint16_t bits_per_sample;
|
||||
char data[4];
|
||||
uint32_t data_size;
|
||||
} wav_header_t;
|
||||
|
||||
/* Fade duration: 75ms at 48kHz = 3600 samples */
|
||||
#define FADE_DURATION_MS 75
|
||||
#define FADE_SAMPLES (48000 * FADE_DURATION_MS / 1000)
|
||||
|
||||
/* FDD audio initialization and cleanup */
|
||||
extern void fdd_audio_init(void);
|
||||
extern void fdd_audio_close(void);
|
||||
|
||||
/* Motor control for audio */
|
||||
extern void fdd_audio_set_motor_enable(int drive, int motor_enable);
|
||||
|
||||
/* Single sector movement audio */
|
||||
extern void fdd_audio_play_single_track_step(int drive, int from_track, int to_track);
|
||||
|
||||
/* Multi-track seek audio */
|
||||
extern void fdd_audio_play_multi_track_seek(int drive, int from_track, int to_track);
|
||||
|
||||
/* Audio callback function */
|
||||
extern void fdd_audio_callback(int16_t *buffer, int length);
|
||||
|
||||
/* State name helper function */
|
||||
extern const char *fdd_audio_motor_state_name(motor_state_t state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*EMU_FDD_AUDIO_H*/
|
||||
@@ -103,12 +103,16 @@ extern void sound_card_reset(void);
|
||||
extern void sound_cd_thread_end(void);
|
||||
extern void sound_cd_thread_reset(void);
|
||||
|
||||
extern void sound_fdd_thread_init(void);
|
||||
extern void sound_fdd_thread_end(void);
|
||||
|
||||
extern void closeal(void);
|
||||
extern void inital(void);
|
||||
extern void givealbuffer(const void *buf);
|
||||
extern void givealbuffer_music(const void *buf);
|
||||
extern void givealbuffer_wt(const void *buf);
|
||||
extern void givealbuffer_cd(const void *buf);
|
||||
extern void givealbuffer_fdd(const void *buf, const uint32_t size);
|
||||
|
||||
#define sb_vibra16c_onboard_relocate_base sb_vibra16s_onboard_relocate_base
|
||||
#define sb_vibra16cl_onboard_relocate_base sb_vibra16s_onboard_relocate_base
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{"requests":[{"kind":"cache","version":2},{"kind":"cmakeFiles","version":1},{"kind":"codemodel","version":2},{"kind":"toolchains","version":1}]}
|
||||
1
src/out/build/x64-Debug/VSInheritEnvironments.txt
Normal file
1
src/out/build/x64-Debug/VSInheritEnvironments.txt
Normal file
@@ -0,0 +1 @@
|
||||
msvc_x64_x64
|
||||
@@ -38,14 +38,15 @@
|
||||
#define I_WT 2
|
||||
#define I_CD 3
|
||||
#define I_MIDI 4
|
||||
#define I_FDD 5
|
||||
|
||||
static int audio[5] = {-1, -1, -1, -1, -1};
|
||||
static int audio[6] = {-1, -1, -1, -1, -1, -1};
|
||||
#ifdef USE_NEW_API
|
||||
static struct audio_swpar info[5];
|
||||
#else
|
||||
static audio_info_t info[5];
|
||||
static audio_info_t info[6];
|
||||
#endif
|
||||
static int freqs[5] = {SOUND_FREQ, MUSIC_FREQ, WT_FREQ, CD_FREQ, 0};
|
||||
static int freqs[6] = {SOUND_FREQ, MUSIC_FREQ, WT_FREQ, CD_FREQ, SOUND_FREQ, 0};
|
||||
|
||||
void closeal(void){
|
||||
int i;
|
||||
@@ -152,6 +153,11 @@ void givealbuffer_wt(const void *buf){
|
||||
void givealbuffer_cd(const void *buf){
|
||||
givealbuffer_common(buf, I_CD, CD_BUFLEN << 1);
|
||||
}
|
||||
|
||||
void givealbuffer_fdd(const void *buf, const uint32_t size){
|
||||
givealbuffer_common(buf, I_FDD, (int) size);
|
||||
}
|
||||
|
||||
void givealbuffer_midi(const void *buf, const uint32_t size){
|
||||
givealbuffer_common(buf, I_MIDI, (int) size);
|
||||
}
|
||||
|
||||
@@ -41,8 +41,9 @@ ALuint buffers[4]; /* front and back buffers */
|
||||
ALuint buffers_music[4]; /* front and back buffers */
|
||||
ALuint buffers_wt[4]; /* front and back buffers */
|
||||
ALuint buffers_cd[4]; /* front and back buffers */
|
||||
ALuint buffers_fdd[4]; /* front and back buffers */
|
||||
ALuint buffers_midi[4]; /* front and back buffers */
|
||||
static ALuint source[5]; /* audio source */
|
||||
static ALuint source[6]; /* audio source - CHANGED FROM 5 TO 6 */
|
||||
|
||||
static int midi_freq = 44100;
|
||||
static int midi_buf_size = 4410;
|
||||
@@ -99,8 +100,9 @@ closeal(void)
|
||||
alSourceStopv(sources, source);
|
||||
alDeleteSources(sources, source);
|
||||
|
||||
if (sources == 4)
|
||||
if (sources >= 6)
|
||||
alDeleteBuffers(4, buffers_midi);
|
||||
alDeleteBuffers(4, buffers_fdd);
|
||||
alDeleteBuffers(4, buffers_cd);
|
||||
alDeleteBuffers(4, buffers_music);
|
||||
alDeleteBuffers(4, buffers);
|
||||
@@ -118,13 +120,15 @@ inital(void)
|
||||
float *wt_buf = NULL;
|
||||
float *cd_buf = NULL;
|
||||
float *midi_buf = NULL;
|
||||
float *fdd_buf = NULL;
|
||||
int16_t *buf_int16 = NULL;
|
||||
int16_t *music_buf_int16 = NULL;
|
||||
int16_t *wt_buf_int16 = NULL;
|
||||
int16_t *cd_buf_int16 = NULL;
|
||||
int16_t *midi_buf_int16 = NULL;
|
||||
int16_t *fdd_buf_int16 = NULL;
|
||||
|
||||
int init_midi = 0;
|
||||
int init_midi = 0;
|
||||
|
||||
if (initialized)
|
||||
return;
|
||||
@@ -136,13 +140,14 @@ inital(void)
|
||||
if ((strcmp(mdn, "none") != 0) && (strcmp(mdn, SYSTEM_MIDI_INTERNAL_NAME) != 0))
|
||||
init_midi = 1; /* If the device is neither none, nor system MIDI, initialize the
|
||||
MIDI buffer and source, otherwise, do not. */
|
||||
sources = 4 + !!init_midi;
|
||||
|
||||
sources = 5 + !!init_midi;
|
||||
if (sound_is_float) {
|
||||
buf = (float *) calloc((BUFLEN << 1), sizeof(float));
|
||||
music_buf = (float *) calloc((MUSICBUFLEN << 1), sizeof(float));
|
||||
wt_buf = (float *) calloc((WTBUFLEN << 1), sizeof(float));
|
||||
cd_buf = (float *) calloc((CD_BUFLEN << 1), sizeof(float));
|
||||
fdd_buf = (float *) calloc((BUFLEN << 1), sizeof(float));
|
||||
if (init_midi)
|
||||
midi_buf = (float *) calloc(midi_buf_size, sizeof(float));
|
||||
} else {
|
||||
@@ -150,48 +155,29 @@ inital(void)
|
||||
music_buf_int16 = (int16_t *) calloc((MUSICBUFLEN << 1), sizeof(int16_t));
|
||||
wt_buf_int16 = (int16_t *) calloc((WTBUFLEN << 1), sizeof(int16_t));
|
||||
cd_buf_int16 = (int16_t *) calloc((CD_BUFLEN << 1), sizeof(int16_t));
|
||||
fdd_buf_int16 = (int16_t *) calloc((BUFLEN << 1), sizeof(int16_t));
|
||||
if (init_midi)
|
||||
midi_buf_int16 = (int16_t *) calloc(midi_buf_size, sizeof(int16_t));
|
||||
}
|
||||
|
||||
alGenBuffers(4, buffers);
|
||||
alGenBuffers(4, buffers_cd);
|
||||
alGenBuffers(4, buffers_fdd);
|
||||
alGenBuffers(4, buffers_music);
|
||||
alGenBuffers(4, buffers_wt);
|
||||
if (init_midi)
|
||||
alGenBuffers(4, buffers_midi);
|
||||
|
||||
if (init_midi)
|
||||
alGenSources(5, source);
|
||||
else
|
||||
alGenSources(4, source);
|
||||
// Create sources: 0=main, 1=music, 2=wt, 3=cd, 4=fdd, 5=midi(optional)
|
||||
alGenSources(sources, source);
|
||||
|
||||
alSource3f(source[0], AL_POSITION, 0.0f, 0.0f, 0.0f);
|
||||
alSource3f(source[0], AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||
alSource3f(source[0], AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
||||
alSourcef(source[0], AL_ROLLOFF_FACTOR, 0.0f);
|
||||
alSourcei(source[0], AL_SOURCE_RELATIVE, AL_TRUE);
|
||||
alSource3f(source[1], AL_POSITION, 0.0f, 0.0f, 0.0f);
|
||||
alSource3f(source[1], AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||
alSource3f(source[1], AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
||||
alSourcef(source[1], AL_ROLLOFF_FACTOR, 0.0f);
|
||||
alSourcei(source[1], AL_SOURCE_RELATIVE, AL_TRUE);
|
||||
alSource3f(source[2], AL_POSITION, 0.0f, 0.0f, 0.0f);
|
||||
alSource3f(source[2], AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||
alSource3f(source[2], AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
||||
alSourcef(source[2], AL_ROLLOFF_FACTOR, 0.0f);
|
||||
alSourcei(source[2], AL_SOURCE_RELATIVE, AL_TRUE);
|
||||
alSource3f(source[3], AL_POSITION, 0.0f, 0.0f, 0.0f);
|
||||
alSource3f(source[3], AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||
alSource3f(source[3], AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
||||
alSourcef(source[3], AL_ROLLOFF_FACTOR, 0.0f);
|
||||
alSourcei(source[3], AL_SOURCE_RELATIVE, AL_TRUE);
|
||||
if (init_midi) {
|
||||
alSource3f(source[4], AL_POSITION, 0.0f, 0.0f, 0.0f);
|
||||
alSource3f(source[4], AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||
alSource3f(source[4], AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
||||
alSourcef(source[4], AL_ROLLOFF_FACTOR, 0.0f);
|
||||
alSourcei(source[4], AL_SOURCE_RELATIVE, AL_TRUE);
|
||||
// Initialize all sources
|
||||
for (int i = 0; i < sources; i++) {
|
||||
alSource3f(source[i], AL_POSITION, 0.0f, 0.0f, 0.0f);
|
||||
alSource3f(source[i], AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||
alSource3f(source[i], AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
||||
alSourcef(source[i], AL_ROLLOFF_FACTOR, 0.0f);
|
||||
alSourcei(source[i], AL_SOURCE_RELATIVE, AL_TRUE);
|
||||
}
|
||||
|
||||
if (sound_is_float) {
|
||||
@@ -199,6 +185,7 @@ inital(void)
|
||||
memset(cd_buf, 0, CD_BUFLEN * 2 * sizeof(float));
|
||||
memset(music_buf, 0, MUSICBUFLEN * 2 * sizeof(float));
|
||||
memset(wt_buf, 0, WTBUFLEN * 2 * sizeof(float));
|
||||
memset(fdd_buf, 0, BUFLEN * 2 * sizeof(float));
|
||||
if (init_midi)
|
||||
memset(midi_buf, 0, midi_buf_size * sizeof(float));
|
||||
} else {
|
||||
@@ -206,6 +193,7 @@ inital(void)
|
||||
memset(cd_buf_int16, 0, CD_BUFLEN * 2 * sizeof(int16_t));
|
||||
memset(music_buf_int16, 0, MUSICBUFLEN * 2 * sizeof(int16_t));
|
||||
memset(wt_buf_int16, 0, WTBUFLEN * 2 * sizeof(int16_t));
|
||||
memset(fdd_buf_int16, 0, BUFLEN * 2 * sizeof(int16_t));
|
||||
if (init_midi)
|
||||
memset(midi_buf_int16, 0, midi_buf_size * sizeof(int16_t));
|
||||
}
|
||||
@@ -216,6 +204,7 @@ inital(void)
|
||||
alBufferData(buffers_music[c], AL_FORMAT_STEREO_FLOAT32, music_buf, MUSICBUFLEN * 2 * sizeof(float), MUSIC_FREQ);
|
||||
alBufferData(buffers_wt[c], AL_FORMAT_STEREO_FLOAT32, wt_buf, WTBUFLEN * 2 * sizeof(float), WT_FREQ);
|
||||
alBufferData(buffers_cd[c], AL_FORMAT_STEREO_FLOAT32, cd_buf, CD_BUFLEN * 2 * sizeof(float), CD_FREQ);
|
||||
alBufferData(buffers_fdd[c], AL_FORMAT_STEREO_FLOAT32, fdd_buf, BUFLEN * 2 * sizeof(float), FREQ);
|
||||
if (init_midi)
|
||||
alBufferData(buffers_midi[c], AL_FORMAT_STEREO_FLOAT32, midi_buf, midi_buf_size * (int) sizeof(float), midi_freq);
|
||||
} else {
|
||||
@@ -223,6 +212,7 @@ inital(void)
|
||||
alBufferData(buffers_music[c], AL_FORMAT_STEREO16, music_buf_int16, MUSICBUFLEN * 2 * sizeof(int16_t), MUSIC_FREQ);
|
||||
alBufferData(buffers_wt[c], AL_FORMAT_STEREO16, wt_buf_int16, WTBUFLEN * 2 * sizeof(int16_t), WT_FREQ);
|
||||
alBufferData(buffers_cd[c], AL_FORMAT_STEREO16, cd_buf_int16, CD_BUFLEN * 2 * sizeof(int16_t), CD_FREQ);
|
||||
alBufferData(buffers_fdd[c], AL_FORMAT_STEREO16, fdd_buf_int16, BUFLEN * 2 * sizeof(int16_t), FREQ);
|
||||
if (init_midi)
|
||||
alBufferData(buffers_midi[c], AL_FORMAT_STEREO16, midi_buf_int16, midi_buf_size * (int) sizeof(int16_t), midi_freq);
|
||||
}
|
||||
@@ -232,14 +222,17 @@ inital(void)
|
||||
alSourceQueueBuffers(source[1], 4, buffers_music);
|
||||
alSourceQueueBuffers(source[2], 4, buffers_wt);
|
||||
alSourceQueueBuffers(source[3], 4, buffers_cd);
|
||||
alSourceQueueBuffers(source[4], 4, buffers_fdd);
|
||||
if (init_midi)
|
||||
alSourceQueueBuffers(source[4], 4, buffers_midi);
|
||||
alSourceQueueBuffers(source[5], 4, buffers_midi);
|
||||
|
||||
alSourcePlay(source[0]);
|
||||
alSourcePlay(source[1]);
|
||||
alSourcePlay(source[2]);
|
||||
alSourcePlay(source[3]);
|
||||
alSourcePlay(source[4]);
|
||||
if (init_midi)
|
||||
alSourcePlay(source[4]);
|
||||
alSourcePlay(source[5]);
|
||||
|
||||
if (sound_is_float) {
|
||||
if (init_midi)
|
||||
@@ -248,6 +241,7 @@ inital(void)
|
||||
free(wt_buf);
|
||||
free(music_buf);
|
||||
free(buf);
|
||||
free(fdd_buf);
|
||||
} else {
|
||||
if (init_midi)
|
||||
free(midi_buf_int16);
|
||||
@@ -255,6 +249,7 @@ inital(void)
|
||||
free(wt_buf_int16);
|
||||
free(music_buf_int16);
|
||||
free(buf_int16);
|
||||
free(fdd_buf_int16);
|
||||
}
|
||||
|
||||
initialized = 1;
|
||||
@@ -319,5 +314,11 @@ givealbuffer_cd(const void *buf)
|
||||
void
|
||||
givealbuffer_midi(const void *buf, const uint32_t size)
|
||||
{
|
||||
givealbuffer_common(buf, 4, (int) size, midi_freq);
|
||||
givealbuffer_common(buf, 5, (int) size, midi_freq);
|
||||
}
|
||||
|
||||
void
|
||||
givealbuffer_fdd(const void *buf, const uint32_t size)
|
||||
{
|
||||
givealbuffer_common(buf, 4, (int) size, FREQ);
|
||||
}
|
||||
@@ -19,7 +19,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <sndio.h>
|
||||
|
||||
#include <86box/86box.h>
|
||||
@@ -31,10 +30,11 @@
|
||||
#define I_WT 2
|
||||
#define I_CD 3
|
||||
#define I_MIDI 4
|
||||
#define I_FDD 5
|
||||
|
||||
static struct sio_hdl* audio[5] = {NULL, NULL, NULL, NULL, NULL};
|
||||
static struct sio_par info[5];
|
||||
static int freqs[5] = {SOUND_FREQ, MUSIC_FREQ, WT_FREQ, CD_FREQ, 0};
|
||||
static struct sio_hdl* audio[6] = {NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
static struct sio_par info[6];
|
||||
static int freqs[6] = { SOUND_FREQ, MUSIC_FREQ, WT_FREQ, CD_FREQ, SOUND_FREQ, 0 };
|
||||
|
||||
void closeal(void){
|
||||
int i;
|
||||
@@ -131,9 +131,14 @@ void givealbuffer_wt(const void *buf){
|
||||
void givealbuffer_cd(const void *buf){
|
||||
givealbuffer_common(buf, I_CD, CD_BUFLEN << 1);
|
||||
}
|
||||
|
||||
void givealbuffer_midi(const void *buf, const uint32_t size){
|
||||
givealbuffer_common(buf, I_MIDI, (int) size);
|
||||
}
|
||||
|
||||
void givealbuffer_fdd(const void *buf, const uint32_t size) {
|
||||
givealbuffer_common(buf, I_FDD, (int) size);
|
||||
}
|
||||
|
||||
void al_set_midi(const int freq, UNUSED(const int buf_size)){
|
||||
freqs[I_MIDI] = freq;
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <86box/timer.h>
|
||||
#include <86box/snd_mpu401.h>
|
||||
#include <86box/sound.h>
|
||||
#include <86box/fdd_audio.h>
|
||||
|
||||
typedef struct {
|
||||
const device_t *device;
|
||||
@@ -55,7 +56,6 @@ int wavetable_pos_global = 0;
|
||||
int sound_gain = 0;
|
||||
|
||||
static sound_handler_t sound_handlers[8];
|
||||
|
||||
static sound_handler_t music_handlers[8];
|
||||
static sound_handler_t wavetable_handlers[8];
|
||||
|
||||
@@ -92,6 +92,13 @@ static int cd_buf_update = CD_BUFLEN / SOUNDBUFLEN;
|
||||
static volatile int cdaudioon = 0;
|
||||
static int cd_thread_enable = 0;
|
||||
|
||||
static thread_t *sound_fdd_thread_h;
|
||||
static event_t *sound_fdd_event;
|
||||
static event_t *sound_fdd_start_event;
|
||||
static int16_t fdd_out_buffer[SOUNDBUFLEN * 2];
|
||||
static volatile int fddaudioon = 0;
|
||||
static int fdd_thread_enable = 0;
|
||||
|
||||
static void (*filter_cd_audio)(int channel, double *buffer, void *priv) = NULL;
|
||||
static void *filter_cd_audio_p = NULL;
|
||||
|
||||
@@ -595,6 +602,9 @@ sound_poll(UNUSED(void *priv))
|
||||
}
|
||||
}
|
||||
|
||||
if (fdd_thread_enable) {
|
||||
thread_set_event(sound_fdd_event);
|
||||
}
|
||||
sound_pos_global = 0;
|
||||
}
|
||||
}
|
||||
@@ -696,17 +706,14 @@ sound_reset(void)
|
||||
inital();
|
||||
|
||||
timer_add(&sound_poll_timer, sound_poll, NULL, 1);
|
||||
|
||||
sound_handlers_num = 0;
|
||||
memset(sound_handlers, 0x00, 8 * sizeof(sound_handler_t));
|
||||
|
||||
timer_add(&music_poll_timer, music_poll, NULL, 1);
|
||||
|
||||
music_handlers_num = 0;
|
||||
memset(music_handlers, 0x00, 8 * sizeof(sound_handler_t));
|
||||
|
||||
timer_add(&wavetable_poll_timer, wavetable_poll, NULL, 1);
|
||||
|
||||
wavetable_handlers_num = 0;
|
||||
memset(wavetable_handlers, 0x00, 8 * sizeof(sound_handler_t));
|
||||
|
||||
@@ -783,3 +790,67 @@ sound_cd_thread_reset(void)
|
||||
|
||||
cd_thread_enable = available_cdrom_drives ? 1 : 0;
|
||||
}
|
||||
|
||||
static void
|
||||
sound_fdd_clean_buffers(void)
|
||||
{
|
||||
memset(fdd_out_buffer, 0, SOUNDBUFLEN * 2);
|
||||
}
|
||||
|
||||
static void
|
||||
sound_fdd_thread(UNUSED(void *param))
|
||||
{
|
||||
thread_set_event(sound_fdd_start_event);
|
||||
while (fddaudioon) {
|
||||
thread_wait_event(sound_fdd_event, -1);
|
||||
thread_reset_event(sound_fdd_event);
|
||||
|
||||
if (!fddaudioon)
|
||||
break;
|
||||
|
||||
static float fdd_float_buffer[SOUNDBUFLEN * 2];
|
||||
memset(fdd_float_buffer, 0, sizeof(fdd_float_buffer));
|
||||
fdd_audio_callback((int16_t*)fdd_float_buffer, SOUNDBUFLEN * 2);
|
||||
givealbuffer_fdd(fdd_float_buffer, SOUNDBUFLEN * 2);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sound_fdd_thread_init(void)
|
||||
{
|
||||
if (!fddaudioon) {
|
||||
fddaudioon = 1;
|
||||
fdd_thread_enable = 1;
|
||||
|
||||
sound_fdd_start_event = thread_create_event();
|
||||
sound_fdd_event = thread_create_event();
|
||||
sound_fdd_thread_h = thread_create(sound_fdd_thread, NULL);
|
||||
|
||||
thread_wait_event(sound_fdd_start_event, -1);
|
||||
thread_reset_event(sound_fdd_start_event);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sound_fdd_thread_end(void)
|
||||
{
|
||||
if (fddaudioon) {
|
||||
fddaudioon = 0;
|
||||
fdd_thread_enable = 0;
|
||||
|
||||
thread_set_event(sound_fdd_event);
|
||||
thread_wait(sound_fdd_thread_h);
|
||||
|
||||
if (sound_fdd_event) {
|
||||
thread_destroy_event(sound_fdd_event);
|
||||
sound_fdd_event = NULL;
|
||||
}
|
||||
|
||||
sound_fdd_thread_h = NULL;
|
||||
|
||||
if (sound_fdd_start_event) {
|
||||
thread_destroy_event(sound_fdd_start_event);
|
||||
sound_fdd_start_event = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,7 @@ static IXAudio2SourceVoice *srcvoicemusic = NULL;
|
||||
static IXAudio2SourceVoice *srcvoicewt = NULL;
|
||||
static IXAudio2SourceVoice *srcvoicemidi = NULL;
|
||||
static IXAudio2SourceVoice *srcvoicecd = NULL;
|
||||
static IXAudio2SourceVoice *srcvoicefdd = NULL;
|
||||
|
||||
#define FREQ SOUND_FREQ
|
||||
#define BUFLEN SOUNDBUFLEN
|
||||
@@ -184,11 +185,18 @@ inital(void)
|
||||
|
||||
(void) IXAudio2_CreateSourceVoice(xaudio2, &srcvoicecd, &fmt, 0, 2.0f, &callbacks, NULL, NULL);
|
||||
|
||||
fmt.nSamplesPerSec = FREQ;
|
||||
fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
|
||||
fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
|
||||
|
||||
(void) IXAudio2_CreateSourceVoice(xaudio2, &srcvoicefdd, &fmt, 0, 2.0f, &callbacks, NULL, NULL);
|
||||
|
||||
(void) IXAudio2SourceVoice_SetVolume(srcvoice, 1, XAUDIO2_COMMIT_NOW);
|
||||
(void) IXAudio2SourceVoice_Start(srcvoice, 0, XAUDIO2_COMMIT_NOW);
|
||||
(void) IXAudio2SourceVoice_Start(srcvoicecd, 0, XAUDIO2_COMMIT_NOW);
|
||||
(void) IXAudio2SourceVoice_Start(srcvoicemusic, 0, XAUDIO2_COMMIT_NOW);
|
||||
(void) IXAudio2SourceVoice_Start(srcvoicewt, 0, XAUDIO2_COMMIT_NOW);
|
||||
(void) IXAudio2SourceVoice_Start(srcvoicefdd, 0, XAUDIO2_COMMIT_NOW);
|
||||
|
||||
const char *mdn = midi_out_device_get_internal_name(midi_output_device_current);
|
||||
|
||||
@@ -218,6 +226,8 @@ closeal(void)
|
||||
(void) IXAudio2SourceVoice_FlushSourceBuffers(srcvoicewt);
|
||||
(void) IXAudio2SourceVoice_Stop(srcvoicecd, 0, XAUDIO2_COMMIT_NOW);
|
||||
(void) IXAudio2SourceVoice_FlushSourceBuffers(srcvoicecd);
|
||||
(void) IXAudio2SourceVoice_Stop(srcvoicefdd, 0, XAUDIO2_COMMIT_NOW);
|
||||
(void) IXAudio2SourceVoice_FlushSourceBuffers(srcvoicefdd);
|
||||
if (srcvoicemidi) {
|
||||
(void) IXAudio2SourceVoice_Stop(srcvoicemidi, 0, XAUDIO2_COMMIT_NOW);
|
||||
(void) IXAudio2SourceVoice_FlushSourceBuffers(srcvoicemidi);
|
||||
@@ -225,13 +235,14 @@ closeal(void)
|
||||
}
|
||||
IXAudio2SourceVoice_DestroyVoice(srcvoicewt);
|
||||
IXAudio2SourceVoice_DestroyVoice(srcvoicecd);
|
||||
IXAudio2SourceVoice_DestroyVoice(srcvoicefdd);
|
||||
IXAudio2SourceVoice_DestroyVoice(srcvoicemusic);
|
||||
IXAudio2SourceVoice_DestroyVoice(srcvoice);
|
||||
IXAudio2MasteringVoice_DestroyVoice(mastervoice);
|
||||
IXAudio2_Release(xaudio2);
|
||||
srcvoice = srcvoicecd = srcvoicemidi = NULL;
|
||||
mastervoice = NULL;
|
||||
xaudio2 = NULL;
|
||||
srcvoice = srcvoicecd = srcvoicemidi = srcvoicefdd = NULL;
|
||||
mastervoice = NULL;
|
||||
xaudio2 = NULL;
|
||||
|
||||
#if defined(_WIN32) && !defined(USE_FAUDIO)
|
||||
dynld_close(xaudio2_handle);
|
||||
@@ -291,6 +302,18 @@ givealbuffer_cd(const void *buf)
|
||||
givealbuffer_common(buf, srcvoicecd, CD_BUFLEN << 1);
|
||||
}
|
||||
|
||||
void
|
||||
givealbuffer_fdd(const void *buf, const uint32_t size)
|
||||
{
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
if (!srcvoicefdd)
|
||||
return;
|
||||
|
||||
givealbuffer_common(buf, srcvoicefdd, size);
|
||||
}
|
||||
|
||||
void
|
||||
al_set_midi(const int freq, const int buf_size)
|
||||
{
|
||||
@@ -324,4 +347,4 @@ void
|
||||
givealbuffer_midi(const void *buf, const uint32_t size)
|
||||
{
|
||||
givealbuffer_common(buf, srcvoicemidi, size);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user