1 /* Copyright (C) 2007-2008 The Android Open Source Project 2 ** 3 ** This software is licensed under the terms of the GNU General Public 4 ** License version 2, as published by the Free Software Foundation, and 5 ** may be copied, distributed, and modified under those terms. 6 ** 7 ** This program is distributed in the hope that it will be useful, 8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 ** GNU General Public License for more details. 11 */ 12 #include "cpu.h" 13 #include "migration/qemu-file.h" 14 #include "hw/android/goldfish/device.h" 15 #include "hw/hw.h" 16 #include "audio/audio.h" 17 #include "android/qemu-debug.h" 18 #include "android/globals.h" 19 20 #define DEBUG 1 21 22 #if DEBUG 23 # define D(...) VERBOSE_PRINT(audio,__VA_ARGS__) 24 #else 25 # define D(...) ((void)0) 26 #endif 27 28 extern void dprint(const char* fmt, ...); 29 30 /* define USE_QEMU_AUDIO_IN to 1 to use QEMU's audio subsystem to 31 * implement the audio input. if 0, this will try to read a .wav file 32 * directly... 33 */ 34 #define USE_QEMU_AUDIO_IN 1 35 36 enum { 37 /* audio status register */ 38 AUDIO_INT_STATUS = 0x00, 39 /* set this to enable IRQ */ 40 AUDIO_INT_ENABLE = 0x04, 41 /* set these to specify buffer addresses */ 42 AUDIO_SET_WRITE_BUFFER_1 = 0x08, 43 AUDIO_SET_WRITE_BUFFER_2 = 0x0C, 44 /* set number of bytes in buffer to write */ 45 AUDIO_WRITE_BUFFER_1 = 0x10, 46 AUDIO_WRITE_BUFFER_2 = 0x14, 47 48 /* true if audio input is supported */ 49 AUDIO_READ_SUPPORTED = 0x18, 50 /* buffer to use for audio input */ 51 AUDIO_SET_READ_BUFFER = 0x1C, 52 53 /* driver writes number of bytes to read */ 54 AUDIO_START_READ = 0x20, 55 56 /* number of bytes available in read buffer */ 57 AUDIO_READ_BUFFER_AVAILABLE = 0x24, 58 59 /* for 64-bit guest CPUs only */ 60 AUDIO_SET_WRITE_BUFFER_1_HIGH = 0x28, 61 AUDIO_SET_WRITE_BUFFER_2_HIGH = 0x30, 62 AUDIO_SET_READ_BUFFER_HIGH = 0x34, 63 64 /* AUDIO_INT_STATUS bits */ 65 66 /* this bit set when it is safe to write more bytes to the buffer */ 67 AUDIO_INT_WRITE_BUFFER_1_EMPTY = 1U << 0, 68 AUDIO_INT_WRITE_BUFFER_2_EMPTY = 1U << 1, 69 AUDIO_INT_READ_BUFFER_FULL = 1U << 2, 70 }; 71 72 struct goldfish_audio_buff { 73 uint64_t address; 74 uint32_t length; 75 uint8* data; 76 uint32_t capacity; 77 uint32_t offset; 78 }; 79 80 81 struct goldfish_audio_state { 82 struct goldfish_device dev; 83 // buffer flags 84 uint32_t int_status; 85 // irq enable mask for int_status 86 uint32_t int_enable; 87 88 #ifndef USE_QEMU_AUDIO_IN 89 // address of the read buffer 90 uint32_t read_buffer; 91 // path to file or device to use for input 92 const char* input_source; 93 // true if input is a wav file 94 int input_is_wav; 95 // true if we need to convert stereo -> mono 96 int input_is_stereo; 97 // file descriptor to use for input 98 int input_fd; 99 #endif 100 101 // number of bytes available in the read buffer 102 int read_buffer_available; 103 104 // set to 1 or 2 to indicate which buffer we are writing from, or zero if both buffers are empty 105 int current_buffer; 106 107 // current data to write 108 struct goldfish_audio_buff out_buff1[1]; 109 struct goldfish_audio_buff out_buff2[1]; 110 struct goldfish_audio_buff in_buff[1]; 111 112 // for QEMU sound output 113 QEMUSoundCard card; 114 SWVoiceOut *voice; 115 #if USE_QEMU_AUDIO_IN 116 SWVoiceIn* voicein; 117 #endif 118 }; 119 120 static void 121 goldfish_audio_buff_init( struct goldfish_audio_buff* b ) 122 { 123 b->address = 0; 124 b->length = 0; 125 b->data = NULL; 126 b->capacity = 0; 127 b->offset = 0; 128 } 129 130 static void 131 goldfish_audio_buff_reset( struct goldfish_audio_buff* b ) 132 { 133 b->offset = 0; 134 b->length = 0; 135 } 136 137 static uint32_t 138 goldfish_audio_buff_length( struct goldfish_audio_buff* b ) 139 { 140 return b->length; 141 } 142 143 static void 144 goldfish_audio_buff_ensure( struct goldfish_audio_buff* b, uint32_t size ) 145 { 146 if (b->capacity < size) { 147 b->data = g_realloc(b->data, size); 148 b->capacity = size; 149 } 150 } 151 152 static void 153 goldfish_audio_buff_set_address( struct goldfish_audio_buff* b, uint32_t addr ) 154 { 155 uint64_set_low(&b->address, addr); 156 } 157 158 static void 159 goldfish_audio_buff_set_address_high( struct goldfish_audio_buff* b, uint32_t addr ) 160 { 161 uint64_set_high(&b->address, addr); 162 } 163 164 static void 165 goldfish_audio_buff_set_length( struct goldfish_audio_buff* b, uint32_t len ) 166 { 167 b->length = len; 168 b->offset = 0; 169 goldfish_audio_buff_ensure(b, len); 170 } 171 172 static void 173 goldfish_audio_buff_read( struct goldfish_audio_buff* b ) 174 { 175 cpu_physical_memory_read(b->address, b->data, b->length); 176 } 177 178 static void 179 goldfish_audio_buff_write( struct goldfish_audio_buff* b ) 180 { 181 cpu_physical_memory_write(b->address, b->data, b->length); 182 } 183 184 static int 185 goldfish_audio_buff_send( struct goldfish_audio_buff* b, int free, struct goldfish_audio_state* s ) 186 { 187 int ret, write = b->length; 188 189 if (write > free) 190 write = free; 191 192 ret = AUD_write(s->voice, b->data + b->offset, write); 193 b->offset += ret; 194 b->length -= ret; 195 return ret; 196 } 197 198 static int 199 goldfish_audio_buff_available( struct goldfish_audio_buff* b ) 200 { 201 return b->length - b->offset; 202 } 203 204 static int 205 goldfish_audio_buff_recv( struct goldfish_audio_buff* b, int avail, struct goldfish_audio_state* s ) 206 { 207 int missing = b->length - b->offset; 208 int avail2 = (avail > missing) ? missing : avail; 209 int read; 210 211 read = AUD_read(s->voicein, b->data + b->offset, avail2 ); 212 if (read == 0) 213 return 0; 214 215 if (avail2 > 0) 216 D("%s: AUD_read(%d) returned %d", __FUNCTION__, avail2, read); 217 218 cpu_physical_memory_write( b->address + b->offset, b->data, read ); 219 b->offset += read; 220 221 return read; 222 } 223 224 /* update this whenever you change the goldfish_audio_state structure */ 225 #define AUDIO_STATE_SAVE_VERSION 3 226 227 #define QFIELD_STRUCT struct goldfish_audio_state 228 QFIELD_BEGIN(audio_state_fields) 229 QFIELD_INT32(int_status), 230 QFIELD_INT32(int_enable), 231 QFIELD_INT32(read_buffer_available), 232 QFIELD_INT32(current_buffer), 233 QFIELD_END 234 235 static void 236 goldfish_audio_buff_put( struct goldfish_audio_buff* b, QEMUFile* f ) 237 { 238 qemu_put_be64(f, b->address ); 239 qemu_put_be32(f, b->length ); 240 qemu_put_be32(f, b->offset ); 241 qemu_put_buffer(f, b->data, b->length ); 242 } 243 244 static void 245 goldfish_audio_buff_get( struct goldfish_audio_buff* b, QEMUFile* f, int version_id ) 246 { 247 if (version_id == (AUDIO_STATE_SAVE_VERSION - 1)) 248 b->address = (uint64_t)qemu_get_be32(f); 249 else 250 b->address = qemu_get_be64(f); 251 b->length = qemu_get_be32(f); 252 b->offset = qemu_get_be32(f); 253 goldfish_audio_buff_ensure(b, b->length); 254 qemu_get_buffer(f, b->data, b->length); 255 } 256 257 static void audio_state_save( QEMUFile* f, void* opaque ) 258 { 259 struct goldfish_audio_state* s = opaque; 260 261 qemu_put_struct(f, audio_state_fields, s); 262 263 goldfish_audio_buff_put (s->out_buff1, f); 264 goldfish_audio_buff_put (s->out_buff2, f); 265 goldfish_audio_buff_put (s->in_buff, f); 266 } 267 268 static int audio_state_load( QEMUFile* f, void* opaque, int version_id ) 269 { 270 struct goldfish_audio_state* s = opaque; 271 int ret; 272 273 if ((version_id != AUDIO_STATE_SAVE_VERSION) && 274 (version_id != (AUDIO_STATE_SAVE_VERSION - 1))) { 275 return -1; 276 } 277 ret = qemu_get_struct(f, audio_state_fields, s); 278 if (!ret) { 279 goldfish_audio_buff_get( s->out_buff1, f, version_id); 280 goldfish_audio_buff_get( s->out_buff2, f, version_id); 281 goldfish_audio_buff_get (s->in_buff, f, version_id); 282 } 283 284 // Similar to enable_audio - without the buffer reset. 285 if (s->voice != NULL) { 286 AUD_set_active_out(s->voice, (s->int_enable & (AUDIO_INT_WRITE_BUFFER_1_EMPTY | AUDIO_INT_WRITE_BUFFER_2_EMPTY)) != 0); 287 } 288 if (s->voicein) { 289 AUD_set_active_in(s->voicein, (s->int_enable & AUDIO_INT_READ_BUFFER_FULL) != 0); 290 } 291 292 // upon snapshot restore we must also re signal the IRQ 293 goldfish_device_set_irq(&s->dev, 0,(s->int_status & s->int_enable)); 294 return ret; 295 } 296 297 static void enable_audio(struct goldfish_audio_state *s, int enable) 298 { 299 // enable or disable the output voice 300 if (s->voice != NULL) { 301 AUD_set_active_out(s->voice, (enable & (AUDIO_INT_WRITE_BUFFER_1_EMPTY | AUDIO_INT_WRITE_BUFFER_2_EMPTY)) != 0); 302 goldfish_audio_buff_reset( s->out_buff1 ); 303 goldfish_audio_buff_reset( s->out_buff2 ); 304 } 305 306 if (s->voicein) { 307 AUD_set_active_in (s->voicein, (enable & AUDIO_INT_READ_BUFFER_FULL) != 0); 308 goldfish_audio_buff_reset( s->in_buff ); 309 } 310 s->current_buffer = 0; 311 } 312 313 #if USE_QEMU_AUDIO_IN 314 static void start_read(struct goldfish_audio_state *s, uint32_t count) 315 { 316 //printf( "... goldfish audio start_read, count=%d\n", count ); 317 goldfish_audio_buff_set_length( s->in_buff, count ); 318 s->read_buffer_available = count; 319 } 320 #else 321 static void start_read(struct goldfish_audio_state *s, uint32_t count) 322 { 323 uint8 wav_header[44]; 324 int result; 325 326 if (!s->input_source) return; 327 328 if (s->input_fd < 0) { 329 s->input_fd = open(s->input_source, O_BINARY | O_RDONLY); 330 331 if (s->input_fd < 0) { 332 fprintf(stderr, "goldfish_audio could not open %s for audio input\n", s->input_source); 333 s->input_source = NULL; // set to to avoid endless retries 334 return; 335 } 336 337 // skip WAV header if we have a WAV file 338 if (s->input_is_wav) { 339 if (read(s->input_fd, wav_header, sizeof(wav_header)) != sizeof(wav_header)) { 340 fprintf(stderr, "goldfish_audio could not read WAV file header %s\n", s->input_source); 341 s->input_fd = -1; 342 s->input_source = NULL; // set to to avoid endless retries 343 return; 344 } 345 346 // is the WAV file stereo? 347 s->input_is_stereo = (wav_header[22] == 2); 348 } else { 349 // assume input from an audio device is stereo 350 s->input_is_stereo = 1; 351 } 352 } 353 354 uint8* buffer = (uint8*)phys_ram_base + s->read_buffer; 355 if (s->input_is_stereo) { 356 // need to read twice as much data 357 count *= 2; 358 } 359 360 try_again: 361 result = read(s->input_fd, buffer, count); 362 if (result == 0 && s->input_is_wav) { 363 // end of file, so seek back to the beginning 364 lseek(s->input_fd, sizeof(wav_header), SEEK_SET); 365 goto try_again; 366 } 367 368 if (result > 0 && s->input_is_stereo) { 369 // we need to convert stereo to mono 370 uint8* src = (uint8*)buffer; 371 uint8* dest = src; 372 int count = result/2; 373 while (count-- > 0) { 374 int sample1 = src[0] | (src[1] << 8); 375 int sample2 = src[2] | (src[3] << 8); 376 int sample = (sample1 + sample2) >> 1; 377 dst[0] = (uint8_t) sample; 378 dst[1] = (uint8_t)(sample >> 8); 379 src += 4; 380 dst += 2; 381 } 382 383 // we reduced the number of bytes by 2 384 result /= 2; 385 } 386 387 s->read_buffer_available = (result > 0 ? result : 0); 388 s->int_status |= AUDIO_INT_READ_BUFFER_FULL; 389 goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable)); 390 } 391 #endif 392 393 static uint32_t goldfish_audio_read(void *opaque, hwaddr offset) 394 { 395 uint32_t ret; 396 struct goldfish_audio_state *s = opaque; 397 switch(offset) { 398 case AUDIO_INT_STATUS: 399 // return current buffer status flags 400 ret = s->int_status & s->int_enable; 401 if(ret) { 402 goldfish_device_set_irq(&s->dev, 0, 0); 403 } 404 return ret; 405 406 case AUDIO_READ_SUPPORTED: 407 #if USE_QEMU_AUDIO_IN 408 D("%s: AUDIO_READ_SUPPORTED returns %d", __FUNCTION__, 409 (s->voicein != NULL)); 410 return (s->voicein != NULL); 411 #else 412 return (s->input_source ? 1 : 0); 413 #endif 414 415 case AUDIO_READ_BUFFER_AVAILABLE: 416 D("%s: AUDIO_READ_BUFFER_AVAILABLE returns %d", __FUNCTION__, 417 s->read_buffer_available); 418 goldfish_audio_buff_write( s->in_buff ); 419 return s->read_buffer_available; 420 421 default: 422 cpu_abort (cpu_single_env, "goldfish_audio_read: Bad offset %x\n", offset); 423 return 0; 424 } 425 } 426 427 static void goldfish_audio_write(void *opaque, hwaddr offset, uint32_t val) 428 { 429 struct goldfish_audio_state *s = opaque; 430 431 switch(offset) { 432 case AUDIO_INT_ENABLE: 433 /* enable buffer empty interrupts */ 434 D("%s: AUDIO_INT_ENABLE %d", __FUNCTION__, val ); 435 enable_audio(s, val); 436 s->int_enable = val; 437 s->int_status = (AUDIO_INT_WRITE_BUFFER_1_EMPTY | AUDIO_INT_WRITE_BUFFER_2_EMPTY); 438 goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable)); 439 break; 440 case AUDIO_SET_WRITE_BUFFER_1: 441 /* save pointer to buffer 1 */ 442 D( "%s: AUDIO_SET_WRITE_BUFFER_1 %08x", __FUNCTION__, val); 443 goldfish_audio_buff_set_address( s->out_buff1, val ); 444 break; 445 case AUDIO_SET_WRITE_BUFFER_1_HIGH: 446 /* save pointer to buffer 1 */ 447 D( "%s: AUDIO_SET_WRITE_BUFFER_1_HIGH %08x", __FUNCTION__, val); 448 goldfish_audio_buff_set_address_high( s->out_buff1, val ); 449 break; 450 case AUDIO_SET_WRITE_BUFFER_2: 451 /* save pointer to buffer 2 */ 452 D( "%s: AUDIO_SET_WRITE_BUFFER_2 %08x", __FUNCTION__, val); 453 goldfish_audio_buff_set_address( s->out_buff2, val ); 454 break; 455 case AUDIO_SET_WRITE_BUFFER_2_HIGH: 456 /* save pointer to buffer 2 */ 457 D( "%s: AUDIO_SET_WRITE_BUFFER_2_HIGH %08x", __FUNCTION__, val); 458 goldfish_audio_buff_set_address_high( s->out_buff2, val ); 459 break; 460 case AUDIO_WRITE_BUFFER_1: 461 /* record that data in buffer 1 is ready to write */ 462 //D( "%s: AUDIO_WRITE_BUFFER_1 %08x", __FUNCTION__, val); 463 if (s->current_buffer == 0) s->current_buffer = 1; 464 goldfish_audio_buff_set_length( s->out_buff1, val ); 465 goldfish_audio_buff_read( s->out_buff1 ); 466 s->int_status &= ~AUDIO_INT_WRITE_BUFFER_1_EMPTY; 467 break; 468 case AUDIO_WRITE_BUFFER_2: 469 /* record that data in buffer 2 is ready to write */ 470 //D( "%s: AUDIO_WRITE_BUFFER_2 %08x", __FUNCTION__, val); 471 if (s->current_buffer == 0) s->current_buffer = 2; 472 goldfish_audio_buff_set_length( s->out_buff2, val ); 473 goldfish_audio_buff_read( s->out_buff2 ); 474 s->int_status &= ~AUDIO_INT_WRITE_BUFFER_2_EMPTY; 475 break; 476 477 case AUDIO_SET_READ_BUFFER: 478 /* save pointer to the read buffer */ 479 goldfish_audio_buff_set_address( s->in_buff, val ); 480 D( "%s: AUDIO_SET_READ_BUFFER %08x", __FUNCTION__, val ); 481 break; 482 483 case AUDIO_START_READ: 484 D( "%s: AUDIO_START_READ %d", __FUNCTION__, val ); 485 start_read(s, val); 486 s->int_status &= ~AUDIO_INT_READ_BUFFER_FULL; 487 goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable)); 488 break; 489 490 case AUDIO_SET_READ_BUFFER_HIGH: 491 /* save pointer to the read buffer */ 492 goldfish_audio_buff_set_address_high( s->in_buff, val ); 493 D( "%s: AUDIO_SET_READ_BUFFER_HIGH %08x", __FUNCTION__, val ); 494 break; 495 496 default: 497 cpu_abort (cpu_single_env, "goldfish_audio_write: Bad offset %x\n", offset); 498 } 499 } 500 501 static void goldfish_audio_callback(void *opaque, int free) 502 { 503 struct goldfish_audio_state *s = opaque; 504 int new_status = 0; 505 506 /* loop until free is zero or both buffers are empty */ 507 while (free && s->current_buffer) { 508 509 /* write data in buffer 1 */ 510 while (free && s->current_buffer == 1) { 511 int written = goldfish_audio_buff_send( s->out_buff1, free, s ); 512 if (written) { 513 D("%s: sent %5d bytes to audio output (buffer 1)", __FUNCTION__, written); 514 free -= written; 515 516 if (goldfish_audio_buff_length( s->out_buff1 ) == 0) { 517 new_status |= AUDIO_INT_WRITE_BUFFER_1_EMPTY; 518 s->current_buffer = (goldfish_audio_buff_length( s->out_buff2 ) ? 2 : 0); 519 } 520 } else { 521 break; 522 } 523 } 524 525 /* write data in buffer 2 */ 526 while (free && s->current_buffer == 2) { 527 int written = goldfish_audio_buff_send( s->out_buff2, free, s ); 528 if (written) { 529 D("%s: sent %5d bytes to audio output (buffer 2)", __FUNCTION__, written); 530 free -= written; 531 532 if (goldfish_audio_buff_length( s->out_buff2 ) == 0) { 533 new_status |= AUDIO_INT_WRITE_BUFFER_2_EMPTY; 534 s->current_buffer = (goldfish_audio_buff_length( s->out_buff1 ) ? 1 : 0); 535 } 536 } else { 537 break; 538 } 539 } 540 } 541 542 if (new_status && new_status != s->int_status) { 543 s->int_status |= new_status; 544 goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable)); 545 } 546 } 547 548 #if USE_QEMU_AUDIO_IN 549 static void 550 goldfish_audio_in_callback(void *opaque, int avail) 551 { 552 struct goldfish_audio_state *s = opaque; 553 int new_status = 0; 554 555 if (goldfish_audio_buff_available( s->in_buff ) == 0 ) 556 return; 557 558 while (avail > 0) { 559 int read = goldfish_audio_buff_recv( s->in_buff, avail, s ); 560 if (read == 0) 561 break; 562 563 avail -= read; 564 565 if (goldfish_audio_buff_available( s->in_buff) == 0) { 566 new_status |= AUDIO_INT_READ_BUFFER_FULL; 567 D("%s: AUDIO_INT_READ_BUFFER_FULL available=%d", 568 __FUNCTION__, goldfish_audio_buff_length( s->in_buff )); 569 break; 570 } 571 } 572 573 if (new_status && new_status != s->int_status) { 574 s->int_status |= new_status; 575 goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable)); 576 } 577 } 578 #endif /* USE_QEMU_AUDIO_IN */ 579 580 static CPUReadMemoryFunc *goldfish_audio_readfn[] = { 581 goldfish_audio_read, 582 goldfish_audio_read, 583 goldfish_audio_read 584 }; 585 586 static CPUWriteMemoryFunc *goldfish_audio_writefn[] = { 587 goldfish_audio_write, 588 goldfish_audio_write, 589 goldfish_audio_write 590 }; 591 592 void goldfish_audio_init(uint32_t base, int id, const char* input_source) 593 { 594 struct goldfish_audio_state *s; 595 struct audsettings as; 596 597 /* nothing to do if no audio input and output */ 598 if (!android_hw->hw_audioOutput && !android_hw->hw_audioInput) 599 return; 600 601 s = (struct goldfish_audio_state *)g_malloc0(sizeof(*s)); 602 s->dev.name = "goldfish_audio"; 603 s->dev.id = id; 604 s->dev.base = base; 605 s->dev.size = 0x1000; 606 s->dev.irq_count = 1; 607 608 #ifndef USE_QEMU_AUDIO_IN 609 s->input_fd = -1; 610 if (input_source) { 611 s->input_source = input_source; 612 char* extension = strrchr(input_source, '.'); 613 if (extension && strcasecmp(extension, ".wav") == 0) { 614 s->input_is_wav = 1; 615 } 616 } 617 #endif 618 619 AUD_register_card( "goldfish_audio", &s->card); 620 621 as.freq = 44100; 622 as.nchannels = 2; 623 as.fmt = AUD_FMT_S16; 624 as.endianness = AUDIO_HOST_ENDIANNESS; 625 626 if (android_hw->hw_audioOutput) { 627 s->voice = AUD_open_out ( 628 &s->card, 629 NULL, 630 "goldfish_audio", 631 s, 632 goldfish_audio_callback, 633 &as 634 ); 635 if (!s->voice) { 636 dprint("warning: opening audio output failed\n"); 637 return; 638 } 639 } 640 641 #if USE_QEMU_AUDIO_IN 642 as.freq = 8000; 643 as.nchannels = 1; 644 as.fmt = AUD_FMT_S16; 645 as.endianness = AUDIO_HOST_ENDIANNESS; 646 647 if (android_hw->hw_audioInput) { 648 s->voicein = AUD_open_in ( 649 &s->card, 650 NULL, 651 "goldfish_audio_in", 652 s, 653 goldfish_audio_in_callback, 654 &as 655 ); 656 if (!s->voicein) { 657 dprint("warning: opening audio input failed\n"); 658 } 659 } 660 #endif 661 662 goldfish_audio_buff_init( s->out_buff1 ); 663 goldfish_audio_buff_init( s->out_buff2 ); 664 goldfish_audio_buff_init( s->in_buff ); 665 666 goldfish_device_add(&s->dev, goldfish_audio_readfn, goldfish_audio_writefn, s); 667 668 register_savevm(NULL, 669 "audio_state", 670 0, 671 AUDIO_STATE_SAVE_VERSION, 672 audio_state_save, 673 audio_state_load, 674 s); 675 } 676 677