Mercurial > octave-nkf
comparison libinterp/dldfcn/audiodevinfo.cc @ 19578:827394ba8eb2
Backed out changeset 5f313345912f
Undo accidental changes from previous changeset.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Wed, 07 Jan 2015 18:11:05 -0500 |
parents | 5f313345912f |
children | c5b8a91baec6 |
comparison
equal
deleted
inserted
replaced
19577:5f313345912f | 19578:827394ba8eb2 |
---|---|
456 void init_fn (void); | 456 void init_fn (void); |
457 void set_y (const octave_value& y); | 457 void set_y (const octave_value& y); |
458 void set_y (octave_function *fn); | 458 void set_y (octave_function *fn); |
459 void set_y (std::string fn); | 459 void set_y (std::string fn); |
460 Matrix& get_y (void); | 460 Matrix& get_y (void); |
461 RowVector get_left (void) const; | 461 RowVector *get_left (void); |
462 RowVector get_right (void) const; | 462 RowVector *get_right (void); |
463 void set_fs (int fs); | 463 void set_fs (int fs); |
464 int get_fs (void); | 464 int get_fs (void); |
465 void set_nbits (int nbits); | 465 void set_nbits (int nbits); |
466 int get_nbits (void); | 466 int get_nbits (void); |
467 void set_id (int id); | 467 void set_id (int id); |
508 | 508 |
509 DECLARE_OCTAVE_ALLOCATOR | 509 DECLARE_OCTAVE_ALLOCATOR |
510 DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA | 510 DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA |
511 }; | 511 }; |
512 | 512 |
513 #define BUFFER_SIZE 8192 | 513 #define BUFFER_SIZE 512 |
514 | 514 |
515 DEFINE_OCTAVE_ALLOCATOR (audioplayer); | 515 DEFINE_OCTAVE_ALLOCATOR (audioplayer); |
516 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (audioplayer, "audioplayer", "audioplayer"); | 516 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (audioplayer, "audioplayer", "audioplayer"); |
517 | 517 |
518 int | 518 int |
530 octave_play_callback (const void *, void *output, unsigned long frames, | 530 octave_play_callback (const void *, void *output, unsigned long frames, |
531 const PaStreamCallbackTimeInfo *, | 531 const PaStreamCallbackTimeInfo *, |
532 PaStreamCallbackFlags, void *data) | 532 PaStreamCallbackFlags, void *data) |
533 { | 533 { |
534 audioplayer *player = static_cast<audioplayer *> (data); | 534 audioplayer *player = static_cast<audioplayer *> (data); |
535 | 535 int big_endian = is_big_endian (); |
536 if (! player) | 536 octave_value_list args, retval; |
537 { | 537 args(0) = frames; |
538 error ("audio player callback function called without player"); | 538 retval = feval (player->octave_callback_function, args, 1); |
539 return paAbort; | 539 RowVector sound_l, sound_r; |
540 } | |
541 | |
542 octave_value_list retval = feval (player->octave_callback_function, | |
543 ovl (static_cast<double> (frames)), 1); | |
544 | |
545 if (error_state || retval.length () < 2) | |
546 { | |
547 error ("audio player callback function failed"); | |
548 return paAbort; | |
549 } | |
550 | |
551 Matrix sound = retval(0).matrix_value (); | 540 Matrix sound = retval(0).matrix_value (); |
552 int return_status = retval(1).int_value (); | 541 int return_status = retval(1).int_value (); |
553 | 542 sound_l.resize (frames); |
554 if (error_state || frames != sound.rows () | 543 sound_r.resize (frames); |
555 || sound.columns () < 1 || sound.columns () > 2) | 544 if (sound.cols () == 1) |
556 { | 545 { |
557 error ("audio player callback function failed"); | 546 for (unsigned long i = 0; i < frames; i++) |
558 return paAbort; | 547 { |
559 } | 548 sound_l(i) = sound(i, 0); |
560 | 549 sound_r(i) = sound(i, 0); |
561 double scale_factor = 1.0; | 550 } |
562 | 551 } |
563 switch (player->get_nbits ()) | 552 else if (sound.cols () == 2) |
564 { | 553 { |
565 case 8: | 554 for (unsigned long i = 0; i < frames; i++) |
566 scale_factor = pow (2.0, 7) - 1.0; | 555 { |
567 break; | 556 sound_l(i) = sound(i, 0); |
568 | 557 sound_r(i) = sound(i, 1); |
569 case 16: | 558 } |
570 scale_factor = pow (2.0, 15) - 1.0; | 559 } |
571 break; | 560 else |
572 | 561 return paAbort; |
573 case 24: | 562 |
574 scale_factor = pow (2.0, 23) - 1.0; | 563 for (unsigned long i = 0; i < frames; i++) |
575 break; | 564 { |
576 | 565 if (player->get_nbits () == 8) |
577 default: | 566 { |
578 error ("invalid player bit depth in callback function"); | 567 int8_t *buffer = static_cast<int8_t *> (output); |
579 break; | 568 buffer[2 * i] = sound_l.elem (i) * (pow (2.0, 7) - 1); |
580 } | 569 buffer[2 * i + 1] = sound_r.elem (i) * (pow (2.0, 7) - 1); |
581 | 570 } |
582 sound = sound * scale_factor; | 571 else if (player->get_nbits () == 16) |
583 | 572 { |
584 const RowVector sound_l = (sound.column (0)).transpose (); | 573 int16_t *buffer = static_cast<int16_t *> (output); |
585 | 574 buffer[2 * i] = sound_l.elem (i) * (pow (2.0, 15) - 1); |
586 const RowVector sound_r = (sound.columns () == 1) | 575 buffer[2 * i + 1] = sound_r.elem (i) * (pow (2.0, 15) - 1); |
587 ? sound_l : (sound.column (1)).transpose (); | 576 } |
588 | 577 else if (player->get_nbits () == 24) |
589 const double *p_l = sound_l.data (); | 578 { |
590 const double *p_r = sound_r.data (); | 579 uint8_t *buffer = static_cast<uint8_t *> (output); |
591 | 580 int32_t sample_l = sound_l.elem (i) * (pow (2.0, 23) - 1); |
592 switch (player->get_nbits ()) | 581 int32_t sample_r = sound_r.elem (i) * (pow (2.0, 23) - 1); |
593 { | 582 sample_l &= 0x00ffffff; |
594 case 8: | 583 sample_r &= 0x00ffffff; |
595 { | 584 // FIXME: Would a mask work better? |
596 int8_t *buffer = static_cast<int8_t *> (output); | 585 uint8_t *_sample_l = reinterpret_cast<uint8_t *> (&sample_l); |
597 | 586 uint8_t *_sample_r = reinterpret_cast<uint8_t *> (&sample_r); |
598 for (unsigned long i = 0; i < frames; i++) | 587 buffer[i * 6 + 0] = _sample_l[0 + big_endian]; |
599 { | 588 buffer[i * 6 + 1] = _sample_l[1 + big_endian]; |
600 buffer[2*i] = p_l[i]; | 589 buffer[i * 6 + 2] = _sample_l[2 + big_endian]; |
601 buffer[2*i+1] = p_r[i]; | 590 buffer[i * 6 + 3] = _sample_r[0 + big_endian]; |
602 } | 591 buffer[i * 6 + 4] = _sample_r[1 + big_endian]; |
603 } | 592 buffer[i * 6 + 5] = _sample_r[2 + big_endian]; |
604 break; | 593 } |
605 | 594 } |
606 case 16: | |
607 { | |
608 int16_t *buffer = static_cast<int16_t *> (output); | |
609 | |
610 for (unsigned long i = 0; i < frames; i++) | |
611 { | |
612 buffer[2*i] = p_l[i]; | |
613 buffer[2*i+1] = p_r[i]; | |
614 } | |
615 } | |
616 break; | |
617 | |
618 case 24: | |
619 { | |
620 int big_endian = is_big_endian (); | |
621 | |
622 uint8_t *buffer = static_cast<uint8_t *> (output); | |
623 | |
624 for (unsigned long i = 0; i < frames; i++) | |
625 { | |
626 int32_t sample_l = p_l[i]; | |
627 int32_t sample_r = p_r[i]; | |
628 | |
629 sample_l &= 0x00ffffff; | |
630 sample_r &= 0x00ffffff; | |
631 | |
632 // FIXME: Would a mask work better? | |
633 uint8_t *_sample_l = reinterpret_cast<uint8_t *> (&sample_l); | |
634 uint8_t *_sample_r = reinterpret_cast<uint8_t *> (&sample_r); | |
635 | |
636 unsigned long offset = i * 6; | |
637 | |
638 buffer[offset+0] = _sample_l[0+big_endian]; | |
639 buffer[offset+1] = _sample_l[1+big_endian]; | |
640 buffer[offset+2] = _sample_l[2+big_endian]; | |
641 | |
642 buffer[offset+3] = _sample_r[0+big_endian]; | |
643 buffer[offset+4] = _sample_r[1+big_endian]; | |
644 buffer[offset+5] = _sample_r[2+big_endian]; | |
645 } | |
646 } | |
647 break; | |
648 | |
649 default: | |
650 error ("invalid player bit depth in callback function"); | |
651 break; | |
652 } | |
653 | |
654 return return_status; | 595 return return_status; |
655 } | 596 } |
656 | 597 |
657 static int | 598 static int |
658 portaudio_play_callback (const void *, void *output, unsigned long frames, | 599 portaudio_play_callback (const void *, void *output, unsigned long frames, |
659 const PaStreamCallbackTimeInfo*, | 600 const PaStreamCallbackTimeInfo*, |
660 PaStreamCallbackFlags, void *data) | 601 PaStreamCallbackFlags, void *data) |
661 { | 602 { |
662 audioplayer *player = static_cast<audioplayer *> (data); | 603 audioplayer *player = static_cast<audioplayer *> (data); |
663 | 604 int big_endian = is_big_endian (); |
664 if (! player) | 605 int channels = player->get_channels (); |
665 { | 606 RowVector *sound_l = player->get_left (); |
666 error ("audio player callback function called without player"); | 607 RowVector *sound_r; |
667 return paAbort; | 608 |
668 } | 609 if (channels > 1) |
669 | 610 sound_r = player->get_right (); |
670 double scale_factor = 1.0; | 611 else |
671 | 612 sound_r = sound_l; |
672 switch (player->get_nbits ()) | 613 |
673 { | 614 for (unsigned long j = 0, k = 0; j < frames; j++, k += 2) |
674 case 8: | 615 { |
675 scale_factor = pow (2.0, 7) - 1.0; | 616 unsigned int sample_number = player->get_sample_number (); |
676 break; | 617 if (sample_number > player->get_end_sample ()) |
677 | 618 return paAbort; |
678 case 16: | 619 |
679 scale_factor = pow (2.0, 15) - 1.0; | 620 if (player->get_type () == DOUBLE) |
680 break; | 621 { |
681 | 622 if (player->get_nbits () == 8) |
682 case 24: | 623 { |
683 scale_factor = pow (2.0, 23) - 1.0; | 624 int8_t *buffer = static_cast<int8_t *> (output); |
684 break; | 625 buffer[k] = sound_l->elem (sample_number) * (pow (2.0, 7) - 1); |
685 | 626 buffer[k + 1] = sound_r->elem (sample_number) * (pow (2.0, 7) - 1); |
686 default: | 627 } |
687 error ("invalid player bit depth in callback function"); | 628 else if (player->get_nbits () == 16) |
688 break; | 629 { |
689 } | 630 int16_t *buffer = static_cast<int16_t *> (output); |
690 | 631 buffer[k] = sound_l->elem (sample_number) * (pow (2.0, 15) - 1); |
691 const RowVector sound_l = player->get_left () * scale_factor; | 632 buffer[k + 1] = sound_r->elem (sample_number) * (pow (2.0, 15) - 1); |
692 const RowVector sound_r = player->get_right () * scale_factor; | 633 } |
693 | 634 else if (player->get_nbits () == 24) |
694 const double *pl = sound_l.data (); | 635 { |
695 const double *pr = sound_l.data (); | 636 uint8_t *buffer = static_cast<uint8_t *> (output); |
696 | 637 int32_t sample_l = sound_l->elem (sample_number) * (pow (2.0, 23) - 1); |
697 if (player->get_type () == DOUBLE) | 638 int32_t sample_r = sound_r->elem (sample_number) * (pow (2.0, 23) - 1); |
698 { | 639 sample_l &= 0x00ffffff; |
699 switch (player->get_nbits ()) | 640 sample_r &= 0x00ffffff; |
700 { | 641 // FIXME: Would a mask work better? |
701 case 8: | 642 uint8_t *_sample_l = reinterpret_cast<uint8_t *> (&sample_l); |
702 { | 643 uint8_t *_sample_r = reinterpret_cast<uint8_t *> (&sample_r); |
703 int8_t *buffer = static_cast<int8_t *> (output); | 644 buffer[j * 6 + 0] = _sample_l[0 + big_endian]; |
704 | 645 buffer[j * 6 + 1] = _sample_l[1 + big_endian]; |
705 for (unsigned long j = 0; j < frames; j++) | 646 buffer[j * 6 + 2] = _sample_l[2 + big_endian]; |
706 { | 647 buffer[j * 6 + 3] = _sample_r[0 + big_endian]; |
707 unsigned int sample_number = player->get_sample_number (); | 648 buffer[j * 6 + 4] = _sample_r[1 + big_endian]; |
708 | 649 buffer[j * 6 + 5] = _sample_r[2 + big_endian]; |
709 if (sample_number >= player->get_end_sample ()) | 650 } |
710 return paComplete; | 651 } |
711 | 652 else if (player->get_type () == INT8) |
712 unsigned long offset = j * 2; | 653 { |
713 | 654 int8_t *buffer = static_cast<int8_t *> (output); |
714 buffer[offset+0] = pl[sample_number]; | 655 buffer[k] = sound_l->elem (sample_number); |
715 buffer[offset+1] = pr[sample_number]; | 656 buffer[k + 1] = sound_r->elem (sample_number); |
716 | 657 } |
717 player->set_sample_number (sample_number + 1); | 658 else if (player->get_type () == UINT8) |
718 } | 659 { |
719 } | 660 uint8_t *buffer = static_cast<uint8_t *> (output); |
720 break; | 661 buffer[k] = sound_l->elem (sample_number); |
721 | 662 buffer[k + 1] = sound_r->elem (sample_number); |
722 case 16: | 663 } |
723 { | 664 else if (player->get_type () == INT16) |
724 int16_t *buffer = static_cast<int16_t *> (output); | 665 { |
725 | 666 int16_t *buffer = static_cast<int16_t *> (output); |
726 for (unsigned long j = 0; j < frames; j++) | 667 buffer[k] = sound_l->elem (sample_number); |
727 { | 668 buffer[k + 1] = sound_r->elem (sample_number); |
728 unsigned int sample_number = player->get_sample_number (); | 669 } |
729 | 670 player->set_sample_number (sample_number + 1); |
730 if (sample_number >= player->get_end_sample ()) | 671 } |
731 return paComplete; | |
732 | |
733 unsigned long offset = j * 2; | |
734 | |
735 buffer[offset+0] = pl[sample_number]; | |
736 buffer[offset+1] = pr[sample_number]; | |
737 | |
738 player->set_sample_number (sample_number + 1); | |
739 } | |
740 } | |
741 break; | |
742 | |
743 case 24: | |
744 { | |
745 uint8_t *buffer = static_cast<uint8_t *> (output); | |
746 | |
747 for (unsigned long j = 0; j < frames; j++) | |
748 { | |
749 unsigned int sample_number = player->get_sample_number (); | |
750 | |
751 if (sample_number >= player->get_end_sample ()) | |
752 return paComplete; | |
753 | |
754 int32_t sample_l = pl[sample_number]; | |
755 int32_t sample_r = pr[sample_number]; | |
756 | |
757 sample_l &= 0x00ffffff; | |
758 sample_r &= 0x00ffffff; | |
759 | |
760 int big_endian = is_big_endian (); | |
761 | |
762 // FIXME: Would a mask work better? | |
763 uint8_t *_sample_l = reinterpret_cast<uint8_t *> (&sample_l); | |
764 uint8_t *_sample_r = reinterpret_cast<uint8_t *> (&sample_r); | |
765 | |
766 unsigned long offset = j * 6; | |
767 | |
768 buffer[offset+0] = _sample_l[0+big_endian]; | |
769 buffer[offset+1] = _sample_l[1+big_endian]; | |
770 buffer[offset+2] = _sample_l[2+big_endian]; | |
771 | |
772 buffer[offset+3] = _sample_r[0+big_endian]; | |
773 buffer[offset+4] = _sample_r[1+big_endian]; | |
774 buffer[offset+5] = _sample_r[2+big_endian]; | |
775 | |
776 player->set_sample_number (sample_number + 1); | |
777 } | |
778 } | |
779 break; | |
780 | |
781 default: | |
782 error ("invalid player bit depth in callback function"); | |
783 break; | |
784 } | |
785 } | |
786 else if (player->get_type () == INT8) | |
787 { | |
788 int8_t *buffer = static_cast<int8_t *> (output); | |
789 | |
790 for (unsigned long j = 0; j < frames; j++) | |
791 { | |
792 unsigned int sample_number = player->get_sample_number (); | |
793 | |
794 if (sample_number >= player->get_end_sample ()) | |
795 return paComplete; | |
796 | |
797 unsigned long offset = j * 2; | |
798 | |
799 buffer[offset+0] = pl[sample_number]; | |
800 buffer[offset+1] = pr[sample_number]; | |
801 | |
802 player->set_sample_number (sample_number + 1); | |
803 } | |
804 } | |
805 else if (player->get_type () == UINT8) | |
806 { | |
807 uint8_t *buffer = static_cast<uint8_t *> (output); | |
808 | |
809 for (unsigned long j = 0; j < frames; j++) | |
810 { | |
811 unsigned int sample_number = player->get_sample_number (); | |
812 | |
813 if (sample_number >= player->get_end_sample ()) | |
814 return paComplete; | |
815 | |
816 unsigned long offset = j * 2; | |
817 | |
818 buffer[offset+0] = pl[sample_number]; | |
819 buffer[offset+1] = pr[sample_number]; | |
820 | |
821 player->set_sample_number (sample_number + 1); | |
822 } | |
823 } | |
824 else if (player->get_type () == INT16) | |
825 { | |
826 int16_t *buffer = static_cast<int16_t *> (output); | |
827 | |
828 for (unsigned long j = 0; j < frames; j++) | |
829 { | |
830 unsigned int sample_number = player->get_sample_number (); | |
831 | |
832 if (sample_number >= player->get_end_sample ()) | |
833 return paComplete; | |
834 | |
835 unsigned long offset = j * 2; | |
836 | |
837 buffer[offset+0] = pl[sample_number]; | |
838 buffer[offset+1] = pr[sample_number]; | |
839 | |
840 player->set_sample_number (sample_number + 1); | |
841 } | |
842 } | |
843 | |
844 return paContinue; | 672 return paContinue; |
845 } | 673 } |
846 | 674 |
847 audioplayer::audioplayer (void) | 675 audioplayer::audioplayer (void) |
848 : octave_callback_function (0), | 676 : octave_callback_function (0), |
971 audioplayer::get_y (void) | 799 audioplayer::get_y (void) |
972 { | 800 { |
973 return y; | 801 return y; |
974 } | 802 } |
975 | 803 |
976 RowVector | 804 RowVector * |
977 audioplayer::get_left (void) const | 805 audioplayer::get_left (void) |
978 { | 806 { |
979 return left; | 807 return &(left); |
980 } | 808 } |
981 | 809 |
982 RowVector | 810 RowVector * |
983 audioplayer::get_right (void) const | 811 audioplayer::get_right (void) |
984 { | 812 { |
985 return channels == 1 ? left : right; | 813 return &(right); |
986 } | 814 } |
987 | 815 |
988 void | 816 void |
989 audioplayer::set_fs (int fs_arg) | 817 audioplayer::set_fs (int fs_arg) |
990 { | 818 { |
2348 | 2176 |
2349 #ifdef HAVE_PORTAUDIO | 2177 #ifdef HAVE_PORTAUDIO |
2350 | 2178 |
2351 int nargin = args.length (); | 2179 int nargin = args.length (); |
2352 | 2180 |
2353 if (nargin < 2) | |
2354 { | |
2355 print_usage (); | |
2356 return retval; | |
2357 } | |
2358 | |
2359 audioplayer* recorder = new audioplayer (); | 2181 audioplayer* recorder = new audioplayer (); |
2360 | 2182 |
2361 bool is_function = args(0).is_string () || args(0).is_function_handle () || args(0).is_inline_function (); | 2183 bool is_function = args(0).is_string () || args(0).is_function_handle () || args(0).is_inline_function (); |
2362 | 2184 |
2363 if (is_function) | 2185 if (is_function) |
2370 switch (nargin) | 2192 switch (nargin) |
2371 { | 2193 { |
2372 case 3: | 2194 case 3: |
2373 recorder->set_nbits (args(2).int_value ()); | 2195 recorder->set_nbits (args(2).int_value ()); |
2374 break; | 2196 break; |
2375 | |
2376 case 4: | 2197 case 4: |
2377 recorder->set_nbits (args(2).int_value ()); | 2198 recorder->set_nbits (args(2).int_value ()); |
2378 recorder->set_id (args(3).int_value ()); | 2199 recorder->set_id (args(3).int_value ()); |
2379 break; | 2200 break; |
2380 } | 2201 } |