15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/* 25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * QEMU Timer based audio emulation 35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * 45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * Copyright (c) 2004-2005 Vassili Karpov (malc) 50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner * 60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner * Permission is hereby granted, free of charge, to any person obtaining a copy 75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * of this software and associated documentation files (the "Software"), to deal 85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * in the Software without restriction, including without limitation the rights 95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * copies of the Software, and to permit persons to whom the Software is 115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * furnished to do so, subject to the following conditions: 125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * 135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * The above copyright notice and this permission notice shall be included in 145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * all copies or substantial portions of the Software. 155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * 165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18136f93a2b660fc780fc2dba82a6f42ca4dc9164aChris Lattner * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19136f93a2b660fc780fc2dba82a6f42ca4dc9164aChris Lattner * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer * THE SOFTWARE. 235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer */ 245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "qemu-common.h" 255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "audio.h" 265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "qemu-timer.h" 275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#define AUDIO_CAP "noaudio" 295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "audio_int.h" 305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencertypedef struct NoVoiceOut { 325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer HWVoiceOut hw; 335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int64_t old_ticks; 345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} NoVoiceOut; 355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencertypedef struct NoVoiceIn { 375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer HWVoiceIn hw; 385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int64_t old_ticks; 395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} NoVoiceIn; 405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic int no_run_out (HWVoiceOut *hw, int live) 425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NoVoiceOut *no = (NoVoiceOut *) hw; 445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int decr, samples; 455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int64_t now; 465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int64_t ticks; 475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int64_t bytes; 485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer now = qemu_get_clock (vm_clock); 505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer ticks = now - no->old_ticks; 515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer bytes = muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ()); 525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer bytes = audio_MIN (bytes, INT_MAX); 535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer samples = bytes >> hw->info.shift; 545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer no->old_ticks = now; 565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer decr = audio_MIN (live, samples); 575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer hw->rpos = (hw->rpos + decr) % hw->samples; 585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return decr; 595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic int no_write (SWVoiceOut *sw, void *buf, int len) 625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return audio_pcm_sw_write (sw, buf, len); 645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic int no_init_out (HWVoiceOut *hw, struct audsettings *as) 675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer audio_pcm_init_info (&hw->info, as); 695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer hw->samples = 1024; 705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void no_fini_out (HWVoiceOut *hw) 745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer (void) hw; 765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic int no_ctl_out (HWVoiceOut *hw, int cmd, ...) 795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer (void) hw; 815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer (void) cmd; 825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic int no_init_in (HWVoiceIn *hw, struct audsettings *as) 865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer audio_pcm_init_info (&hw->info, as); 885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer hw->samples = 1024; 895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 90b8128140956c6f8f0ab143818775a81f4b4aa477Chris Lattner} 915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void no_fini_in (HWVoiceIn *hw) 935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer (void) hw; 955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 9698be4943e8dc4f3905629a7102668960873cf863Chris Lattner 979c728dc4d8da89c73fcae74c9e72d7a83ffd7b6dTed Kremenekstatic int no_run_in (HWVoiceIn *hw) 985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer NoVoiceIn *no = (NoVoiceIn *) hw; 1005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int live = audio_pcm_hw_get_live_in (hw); 1015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int dead = hw->samples - live; 1025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int samples = 0; 1035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (dead) { 1055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int64_t now = qemu_get_clock (vm_clock); 1065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int64_t ticks = now - no->old_ticks; 1075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int64_t bytes = 1085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ()); 1095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer no->old_ticks = now; 1115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer bytes = audio_MIN (bytes, INT_MAX); 1125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer samples = bytes >> hw->info.shift; 1135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer samples = audio_MIN (samples, dead); 1145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 1155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return samples; 1165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 1175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic int no_read (SWVoiceIn *sw, void *buf, int size) 1195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 1205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int samples = size >> sw->info.shift; 1215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int total = sw->hw->total_samples_captured - sw->total_hw_samples_acquired; 1225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer int to_clear = audio_MIN (samples, total); 1235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer audio_pcm_info_clear_buf (&sw->info, buf, to_clear); 1245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return to_clear; 12598be4943e8dc4f3905629a7102668960873cf863Chris Lattner} 1269c728dc4d8da89c73fcae74c9e72d7a83ffd7b6dTed Kremenek 1275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic int no_ctl_in (HWVoiceIn *hw, int cmd, ...) 1285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 1295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer (void) hw; 1305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer (void) cmd; 1315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 1325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 1335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void *no_audio_init (void) 1355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 1365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &no_audio_init; 1375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 1385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic void no_audio_fini (void *opaque) 1405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer{ 1415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer (void) opaque; 1425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 1435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstatic struct audio_pcm_ops no_pcm_ops = { 1455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer .init_out = no_init_out, 1465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer .fini_out = no_fini_out, 1475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer .run_out = no_run_out, 1485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer .write = no_write, 1495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer .ctl_out = no_ctl_out, 1505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer .init_in = no_init_in, 1525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer .fini_in = no_fini_in, 1535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer .run_in = no_run_in, 1545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer .read = no_read, 1555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer .ctl_in = no_ctl_in 1565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}; 1575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerstruct audio_driver no_audio_driver = { 1595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer .name = "none", 1605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer .descr = "Timer based audio emulation", 1615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer .options = NULL, 1625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer .init = no_audio_init, 1635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer .fini = no_audio_fini, 1645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer .pcm_ops = &no_pcm_ops, 1655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer .can_be_default = 1, 1665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer .max_voices_out = INT_MAX, 1675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer .max_voices_in = INT_MAX, 1685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer .voice_size_out = sizeof (NoVoiceOut), 1695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer .voice_size_in = sizeof (NoVoiceIn) 1705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}; 1715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer