diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c6cbe56
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..b608edd
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+Music Synthesizer
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..96cc43e
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
new file mode 100644
index 0000000..e7bedf3
--- /dev/null
+++ b/.idea/copyright/profiles_settings.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..97626ba
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000..508b3d9
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..5d19981
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..37a85bd
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644
index 0000000..7f68460
--- /dev/null
+++ b/.idea/runConfigurations.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/.classpath b/android/.classpath
deleted file mode 100644
index bea3b48..0000000
--- a/android/.classpath
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/android/.externalToolBuilders/NDK Builder.launch b/android/.externalToolBuilders/NDK Builder.launch
deleted file mode 100644
index 18993b1..0000000
--- a/android/.externalToolBuilders/NDK Builder.launch
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/android/.externalToolBuilders/Proto Builder.launch b/android/.externalToolBuilders/Proto Builder.launch
deleted file mode 100644
index 18b99a6..0000000
--- a/android/.externalToolBuilders/Proto Builder.launch
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/android/.gitignore b/android/.gitignore
deleted file mode 100644
index 67a5cb9..0000000
--- a/android/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Android NDK output files
-obj/**
-libs/**
\ No newline at end of file
diff --git a/android/.project b/android/.project
deleted file mode 100644
index 6c6f44d..0000000
--- a/android/.project
+++ /dev/null
@@ -1,75 +0,0 @@
-
-
- MusicSynthesizer
-
-
-
-
-
- org.eclipse.ui.externaltools.ExternalToolBuilder
- auto,full,incremental,
-
-
- LaunchConfigHandle
- <project>/.externalToolBuilders/Proto Builder.launch
-
-
-
-
- org.eclipse.ui.externaltools.ExternalToolBuilder
- auto,full,incremental,
-
-
- LaunchConfigHandle
- <project>/.externalToolBuilders/NDK Builder.launch
-
-
-
-
- com.android.ide.eclipse.adt.ResourceManagerBuilder
-
-
-
-
- com.android.ide.eclipse.adt.PreCompilerBuilder
-
-
-
-
- org.eclipse.jdt.core.javabuilder
-
-
-
-
- com.android.ide.eclipse.adt.ApkBuilder
-
-
-
-
-
- com.android.ide.eclipse.adt.AndroidNature
- org.eclipse.jdt.core.javanature
-
-
-
- core
- 2
- PARENT-1-PROJECT_LOC/core/src
-
-
- core-gen
- 2
- PARENT-1-PROJECT_LOC/core/gen
-
-
- core-lib
- 2
- PARENT-1-PROJECT_LOC/core/lib
-
-
- test
- 2
- PARENT-1-PROJECT_LOC/test/src
-
-
-
diff --git a/android/.settings/org.eclipse.jdt.core.prefs b/android/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index 5c9506e..0000000
--- a/android/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,280 +0,0 @@
-#Thu Jan 27 01:33:26 PST 2011
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
-org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.5
-org.eclipse.jdt.core.compiler.debug.lineNumber=generate
-org.eclipse.jdt.core.compiler.debug.localVariable=generate
-org.eclipse.jdt.core.compiler.debug.sourceFile=generate
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.5
-org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
-org.eclipse.jdt.core.formatter.alignment_for_assignment=0
-org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
-org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
-org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
-org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
-org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
-org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
-org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
-org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
-org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
-org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
-org.eclipse.jdt.core.formatter.blank_lines_after_package=1
-org.eclipse.jdt.core.formatter.blank_lines_before_field=0
-org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
-org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
-org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
-org.eclipse.jdt.core.formatter.blank_lines_before_method=1
-org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
-org.eclipse.jdt.core.formatter.blank_lines_before_package=0
-org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
-org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
-org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
-org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
-org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
-org.eclipse.jdt.core.formatter.comment.format_block_comments=true
-org.eclipse.jdt.core.formatter.comment.format_header=false
-org.eclipse.jdt.core.formatter.comment.format_html=true
-org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
-org.eclipse.jdt.core.formatter.comment.format_line_comments=true
-org.eclipse.jdt.core.formatter.comment.format_source_code=true
-org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
-org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
-org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
-org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
-org.eclipse.jdt.core.formatter.comment.line_length=100
-org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
-org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
-org.eclipse.jdt.core.formatter.compact_else_if=true
-org.eclipse.jdt.core.formatter.continuation_indentation=4
-org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=4
-org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
-org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
-org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
-org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
-org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
-org.eclipse.jdt.core.formatter.indent_empty_lines=false
-org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
-org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
-org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
-org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
-org.eclipse.jdt.core.formatter.indentation.size=2
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
-org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
-org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
-org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
-org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
-org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.join_lines_in_comments=true
-org.eclipse.jdt.core.formatter.join_wrapped_lines=true
-org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=true
-org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
-org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
-org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=true
-org.eclipse.jdt.core.formatter.lineSplit=100
-org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
-org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
-org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
-org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
-org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
-org.eclipse.jdt.core.formatter.tabulation.char=space
-org.eclipse.jdt.core.formatter.tabulation.size=2
-org.eclipse.jdt.core.formatter.use_on_off_tags=false
-org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true
-org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
-org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/android/.settings/org.eclipse.jdt.ui.prefs b/android/.settings/org.eclipse.jdt.ui.prefs
deleted file mode 100644
index a26edcc..0000000
--- a/android/.settings/org.eclipse.jdt.ui.prefs
+++ /dev/null
@@ -1,8 +0,0 @@
-#Thu Jan 27 01:35:20 PST 2011
-eclipse.preferences.version=1
-formatter_profile=_MusicSynthesizer
-formatter_settings_version=11
-org.eclipse.jdt.ui.ignorelowercasenames=true
-org.eclipse.jdt.ui.importorder=java;javax;org;com;
-org.eclipse.jdt.ui.ondemandthreshold=99
-org.eclipse.jdt.ui.staticondemandthreshold=99
diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml
deleted file mode 100644
index 82fc6fb..0000000
--- a/android/AndroidManifest.xml
+++ /dev/null
@@ -1,84 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/android/default.properties b/android/default.properties
deleted file mode 100644
index 4686f7f..0000000
--- a/android/default.properties
+++ /dev/null
@@ -1,11 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system use,
-# "build.properties", and override values to adapt the script to your
-# project structure.
-
-# Project target.
-target=android-9
diff --git a/android/jni/Android.mk b/android/jni/Android.mk
deleted file mode 100644
index 1c3e7ea..0000000
--- a/android/jni/Android.mk
+++ /dev/null
@@ -1,88 +0,0 @@
-LOCAL_PATH := $(call my-dir)/../../cpp/src
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := synth
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_SRC_FILES := android_glue.cc \
- dx7note.cc \
- env.cc \
- exp2.cc \
- fir.cc \
- fm_core.cc \
- fm_op_kernel.cc \
- freqlut.cc \
- lfo.cc \
- patch.cc \
- pitchenv.cc \
- resofilter.cc \
- ringbuffer.cc \
- sawtooth.cc \
- sin.cc \
- synth_unit.cc
-
-ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
- LOCAL_ARM_NEON := true
- LOCAL_CFLAGS := -DHAVE_NEON=1
- LOCAL_SRC_FILES += neon_fm_kernel.s \
- neon_ladder.s \
- neon_fir.s
-endif
-
-# for native audio
-LOCAL_LDLIBS += -lOpenSLES
-# for logging
-LOCAL_LDLIBS += -llog
-
-LOCAL_STATIC_LIBRARIES += cpufeatures
-
-LOCAL_CFLAGS += -O3
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := test_neon.cc \
- resofilter.cc
-
-ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
- LOCAL_ARM_NEON := true
- LOCAL_CFLAGS := -DHAVE_NEON=1
- LOCAL_SRC_FILES += neon_fm_kernel.s \
- neon_ladder.s \
- neon_fir.s
-endif
-
-LOCAL_CFLAGS += -O3
-
-LOCAL_STATIC_LIBRARIES += cpufeatures
-
-LOCAL_MODULE := test_neon
-
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := test_filter.cc \
- fir.cc \
- sawtooth.cc \
- exp2.cc \
- sin.cc \
- fm_op_kernel.cc \
- resofilter.cc \
- freqlut.cc
-
-ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
- LOCAL_ARM_NEON := true
- LOCAL_CFLAGS := -DHAVE_NEON=1
- LOCAL_SRC_FILES += neon_fir.s \
- neon_iir.s \
- neon_fm_kernel.s \
- neon_ladder.s
-endif
-
-LOCAL_CFLAGS += -O3
-LOCAL_STATIC_LIBRARIES += cpufeatures
-LOCAL_MODULE := test_filter
-include $(BUILD_EXECUTABLE)
-
-
-$(call import-module,android/cpufeatures)
diff --git a/android/jni/Application.mk b/android/jni/Application.mk
deleted file mode 100644
index 3d53443..0000000
--- a/android/jni/Application.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-APP_ABI := all
-
diff --git a/android/project.properties b/android/project.properties
deleted file mode 100644
index a3ee5ab..0000000
--- a/android/project.properties
+++ /dev/null
@@ -1,14 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system edit
-# "ant.properties", and override values to adapt the script to your
-# project structure.
-#
-# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
-#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
-
-# Project target.
-target=android-17
diff --git a/android/src/com/levien/synthesizer/android/Storage.java b/android/src/com/levien/synthesizer/android/Storage.java
deleted file mode 100644
index de4cf81..0000000
--- a/android/src/com/levien/synthesizer/android/Storage.java
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.os.Environment;
-import android.widget.EditText;
-import android.widget.Toast;
-
-import com.levien.synthesizer.core.music.Music.Score;
-
-/**
- * A collection of functions for storing and retrieving scores.
- */
-public class Storage {
- /**
- * Opens the score stored with the name "_default", which should always be the current score
- * being edited. This may be called at any time to restore saved state, since Android Activities
- * can come and go.
- *
- * @param score - The mutable score to populate with the stored data.
- * @param context - Android application context.
- */
- public static void openDefaultScore(Score.Builder score, Context context) throws IOException {
- openScore(score, "_default", context);
- }
-
- /**
- * Saves a score with the name "_default", which should always be the current score being edited.
- * This may be called at any time to save state, since Android Activities can come and go.
- *
- * @param score - The score data to save.
- * @param context - Android application context.
- */
- public static void saveDefaultScore(Score score, Context context) throws IOException {
- saveScore(score, "_default", true, context);
- }
-
- /**
- * Opens the score with the given name. The name should be name of a valid score file in storage.
- * The file must be in the root external files directory for the app.
- *
- * @param score - The mutable score to update with the data from storage.
- * @param name - The name of the file, minus the ".pb" extension.
- * @param context - The Android application context.
- */
- public static void openScore(Score.Builder score, String name, Context context) throws IOException {
- if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) &&
- !Environment.MEDIA_MOUNTED_READ_ONLY.equals(Environment.getExternalStorageState())) {
- throw new IOException("External storage is not readable.");
- }
- File path = context.getExternalFilesDir(null);
- File file = new File(path, name + ".pb");
- FileInputStream in = new FileInputStream(file);
- score.clear();
- score.mergeFrom(in);
- in.close();
- }
-
- /**
- * Saves the score with the given name. Files are stored in the root external files directory for
- * the app.
- *
- * @param score - The score to save.
- * @param name - The name of the file, without any extension.
- * @param overwrite - If true, replace the existing file, if one already exists.
- * @param context - The Android application context.
- * @throws IOException - On any kind of IO error, or if name is "", or the file already exists.
- */
- public static void saveScore(Score score,
- String name,
- boolean overwrite,
- Context context) throws IOException {
- if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
- throw new IOException("External storage is not writeable.");
- }
- File path = context.getExternalFilesDir(null);
- name = cleanupName(name);
- if (name.length() == 0) {
- throw new IOException("Can't save score without a name.");
- }
- File file = new File(path, name + ".pb");
- if (!overwrite && file.exists()) {
- throw new IOException("File already exists.");
- }
- FileOutputStream out = new FileOutputStream(file);
- score.writeTo(out);
- out.close();
- }
-
- /**
- * Returns the list of all valid names of scores that are currently in storage.
- */
- public static String[] getScoreNames(Context context) throws IOException {
- if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) &&
- !Environment.MEDIA_MOUNTED_READ_ONLY.equals(Environment.getExternalStorageState())) {
- throw new IOException("External storage is not readable.");
- }
- File path = context.getExternalFilesDir(null);
- File[] files = path.listFiles();
- ArrayList names = new ArrayList();
- for (File file : files) {
- names.add(file.getName().replaceAll("\\.pb", ""));
- }
- return names.toArray(new String[0]);
- }
-
- /**
- * Returns true iff there is a score in storage with the given name.
- */
- public static boolean scoreExists(String name, Context context) throws IOException {
- String[] names = getScoreNames(context);
- for (String existingName : names) {
- if (name.equals(existingName)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Interface used to notify callers of openScoreWithDialog() when the opening has completed.
- */
- public interface OpenScoreListener {
- void onOpenScore(Score.Builder score);
- }
-
- /**
- * Shows UI to allow the user to pick one of the current scores in storage, and then populates
- * score with the data from that file.
- *
- * @param score - The mutable score to update.
- * @param listener - A listener that is notified after the score is updated. Can be null.
- * @param context - An Android application context.
- */
- public static void openScoreWithDialog(final Score.Builder score,
- final OpenScoreListener listener,
- final Context context) {
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle("Open score...");
- try {
- final String[] scoreNames = getScoreNames(context);
- builder.setItems(scoreNames, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- try {
- openScore(score, scoreNames[which], context);
- if (listener != null) {
- listener.onOpenScore(score);
- }
- dialog.dismiss();
- } catch (IOException e) {
- Logger logger = Logger.getLogger(Storage.class.getName());
- logger.log(Level.SEVERE,
- "Error opening score \"" + scoreNames[which] + "\" with dialog.", e);
- Toast.makeText(context,
- "Unable to open \"" + scoreNames[which] + "\".",
- Toast.LENGTH_SHORT).show();
- }
- }
- });
- } catch (IOException e) {
- Logger logger = Logger.getLogger(Storage.class.getName());
- logger.log(Level.SEVERE,
- "Error getting score names.", e);
- Toast.makeText(context,
- "Unable to get existing score names.",
- Toast.LENGTH_SHORT).show();
- }
- AlertDialog dialog = builder.create();
- dialog.show();
- }
-
- /**
- * Shows UI to allow the user to pick a name and save the given score in storage.
- *
- * @param score - The score to save.
- * @param context - An Android application context.
- */
- public static void saveScoreWithDialog(final Score score,
- final Context context) {
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle("Save score as...");
- builder.setMessage("Name: ");
- final EditText input = new EditText(context);
- builder.setView(input);
- builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- public void onClick(final DialogInterface nameDialog, int which) {
- final String name = cleanupName(input.getText().toString());
- if (name.length() == 0) {
- Toast.makeText(context,
- "Name must not be empty.",
- Toast.LENGTH_SHORT).show();
- } else {
- try {
- if (scoreExists(name, context)) {
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle("Overwrite?");
- builder.setMessage(
- "A score named " + name + " already exists. Would you like to overwrite it?");
- builder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface confirmDialog, int which) {
- try {
- saveScore(score, name, true, context);
- confirmDialog.dismiss();
- nameDialog.dismiss();
- } catch (IOException e) {
- Logger logger = Logger.getLogger(Storage.class.getName());
- logger.log(Level.SEVERE,
- "Error saving score \"" + name + "\" with dialog.", e);
- Toast.makeText(context,
- "Unable to save \"" + name + "\".",
- Toast.LENGTH_SHORT).show();
- }
- }
- });
- builder.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- }
- });
- AlertDialog confirmDialog = builder.create();
- confirmDialog.show();
- } else {
- saveScore(score, name, false, context);
- nameDialog.dismiss();
- }
- } catch (IOException e) {
- Logger logger = Logger.getLogger(Storage.class.getName());
- logger.log(Level.SEVERE,
- "Error saving score \"" + name + "\" with dialog.", e);
- Toast.makeText(context,
- "Unable to save \"" + name + "\".",
- Toast.LENGTH_SHORT).show();
- }
- }
- }
- });
- builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- }
- });
- AlertDialog dialog = builder.create();
- dialog.show();
- }
-
- /**
- * Internal method to turn a user input string into a valid file name.
- */
- private static String cleanupName(String name) {
- name = name.trim();
- name = name.replaceAll("[^A-Za-z0-9_-]", "_");
- return name;
- }
-}
diff --git a/android/src/com/levien/synthesizer/android/ui/AmplificationActivity.java b/android/src/com/levien/synthesizer/android/ui/AmplificationActivity.java
deleted file mode 100644
index f7ccd9e..0000000
--- a/android/src/com/levien/synthesizer/android/ui/AmplificationActivity.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.ui;
-
-import android.os.Bundle;
-import com.levien.synthesizer.R;
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
-import com.levien.synthesizer.core.model.composite.Presets.Setting;
-import com.levien.synthesizer.android.widgets.knob.KnobView;
-import com.levien.synthesizer.android.widgets.piano.PianoView;
-
-/**
- * Activity for modifying amplification/adsr envelope.
- * TODO(klimt): Add the ability to switch channels.
- */
-public class AmplificationActivity extends SynthesizerActivity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.amplification);
-
- attackKnob_ = (KnobView)findViewById(R.id.attackKnob);
- decayKnob_ = (KnobView)findViewById(R.id.decayKnob);
- sustainKnob_ = (KnobView)findViewById(R.id.sustainKnob);
- releaseKnob_ = (KnobView)findViewById(R.id.releaseKnob);
- volumeKnob_ = (KnobView)findViewById(R.id.volumeKnob);
- piano_ = (PianoView)findViewById(R.id.piano);
- }
-
- @Override
- protected void onSynthesizerUpdate(MultiChannelSynthesizer synth) {
- int channel = getIntentChannel(this);
- attackKnob_.bindTo(synthesizer_, channel, Setting.ATTACK);
- decayKnob_.bindTo(synthesizer_, channel, Setting.DECAY);
- sustainKnob_.bindTo(synthesizer_, channel, Setting.SUSTAIN);
- releaseKnob_.bindTo(synthesizer_, channel, Setting.RELEASE);
- volumeKnob_.bindTo(synthesizer_, channel, Setting.VOLUME);
- piano_.bindTo(synthesizer_, channel);
- }
-
- private KnobView attackKnob_;
- private KnobView decayKnob_;
- private KnobView sustainKnob_;
- private KnobView releaseKnob_;
- private KnobView volumeKnob_;
- private PianoView piano_;
-}
diff --git a/android/src/com/levien/synthesizer/android/ui/ChordGridActivity.java b/android/src/com/levien/synthesizer/android/ui/ChordGridActivity.java
deleted file mode 100644
index d9195c6..0000000
--- a/android/src/com/levien/synthesizer/android/ui/ChordGridActivity.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.ui;
-
-import java.util.ArrayList;
-
-import android.os.Bundle;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemSelectedListener;
-import android.widget.ArrayAdapter;
-import android.widget.Spinner;
-
-import com.levien.synthesizer.R;
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
-import com.levien.synthesizer.android.widgets.ChordGridView;
-
-/**
- * Activity for playing whole chords at a time, arranged in a circle of fifths.
- */
-public class ChordGridActivity extends SynthesizerActivity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.chord_grid);
-
- chordGrid_ = (ChordGridView)findViewById(R.id.chord_grid);
- presetSpinner_ = (Spinner)findViewById(R.id.presetSpinner);
-
- presetSpinner_.setOnItemSelectedListener(new OnItemSelectedListener() {
- public void onItemSelected(AdapterView> parent, View view, int position, long id) {
- if (synthesizer_ == null) {
- return;
- }
- if (position > 0) {
- chordGrid_.bindTo(synthesizer_, position - 1);
- }
- }
- public void onNothingSelected(AdapterView> parent) {
- }
- });
- }
-
- @Override
- protected void onSynthesizerUpdate(MultiChannelSynthesizer synth) {
- chordGrid_.bindTo(synthesizer_, 0);
-
- ArrayList presetNames = new ArrayList();
- presetNames.add("");
- synthesizer_.getPresetNames(presetNames);
- ArrayAdapter adapter = new ArrayAdapter(
- this, android.R.layout.simple_spinner_item, presetNames);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- presetSpinner_.setAdapter(adapter);
- }
-
- private ChordGridView chordGrid_;
- private Spinner presetSpinner_;
-}
diff --git a/android/src/com/levien/synthesizer/android/ui/EditInstrumentActivity.java b/android/src/com/levien/synthesizer/android/ui/EditInstrumentActivity.java
deleted file mode 100644
index cc4a8e2..0000000
--- a/android/src/com/levien/synthesizer/android/ui/EditInstrumentActivity.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.ui;
-
-import android.app.ListActivity;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.view.View;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-
-import com.levien.synthesizer.R;
-import com.levien.synthesizer.core.model.composite.Presets.Setting;
-import com.levien.synthesizer.android.service.SynthesizerService;
-
-/**
- * An Activity to let the user choose a subset of a presets settings in order to edit them.
- */
-public class EditInstrumentActivity extends ListActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState){
- super.onCreate(savedInstanceState);
- String[] sections = getResources().getStringArray(R.array.sections);
- ArrayAdapter adapter = new ArrayAdapter(
- this, android.R.layout.simple_list_item_1, sections);
- setListAdapter(adapter);
- }
-
- @Override
- protected void onStart() {
- super.onStart();
- bindService(new Intent(this, SynthesizerService.class),
- synthesizerConnection_, Context.BIND_AUTO_CREATE);
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- unbindService(synthesizerConnection_);
- }
-
- @Override
- protected void onListItemClick(ListView list, View view, int position, long id) {
- int channel = SynthesizerActivity.getIntentChannel(this);
- switch (position) {
- case 0:
- this.startActivity(new Intent(null,
- SynthesizerActivity.makeUri(channel),
- this,
- VibratoActivity.class));
- break;
- case 1:
- this.startActivity(new Intent(null, SynthesizerActivity.makeUri(
- channel,
- Setting.OSCILLATOR_1_WAVEFORM,
- Setting.OSCILLATOR_1_GLIDE,
- Setting.OSCILLATOR_1_COARSE,
- Setting.OSCILLATOR_1_FINE,
- Setting.OSCILLATOR_1_VIBRATO,
- Setting.BALANCE),
- this, OscillatorActivity.class));
- break;
- case 2:
- this.startActivity(new Intent(null, SynthesizerActivity.makeUri(
- channel,
- Setting.OSCILLATOR_2_WAVEFORM,
- Setting.OSCILLATOR_2_GLIDE,
- Setting.OSCILLATOR_2_COARSE,
- Setting.OSCILLATOR_2_FINE,
- Setting.OSCILLATOR_2_VIBRATO,
- Setting.BALANCE),
- this, OscillatorActivity.class));
- break;
- case 3:
- this.startActivity(new Intent(null, SynthesizerActivity.makeUri(
- channel,
- Setting.OSCILLATOR_1_BLEND,
- Setting.OSCILLATOR_1_STRETCH,
- Setting.OSCILLATOR_1_EXCITEMENT),
- this, KarplusStrongActivity.class));
- break;
- case 4:
- this.startActivity(new Intent(null, SynthesizerActivity.makeUri(
- channel,
- Setting.OSCILLATOR_2_BLEND,
- Setting.OSCILLATOR_2_STRETCH,
- Setting.OSCILLATOR_2_EXCITEMENT),
- this, KarplusStrongActivity.class));
- break;
- case 5:
- this.startActivity(new Intent(null,
- SynthesizerActivity.makeUri(channel),
- this,
- TremoloActivity.class));
- break;
- case 6:
- this.startActivity(new Intent(null,
- SynthesizerActivity.makeUri(channel),
- this,
- LowPassFilterActivity.class));
- break;
- case 7:
- this.startActivity(new Intent(null,
- SynthesizerActivity.makeUri(channel),
- this,
- AmplificationActivity.class));
- break;
- case 8:
- this.startActivity(new Intent(null,
- SynthesizerActivity.makeUri(channel),
- this,
- EffectsActivity.class));
- break;
- }
- }
-
- private ServiceConnection synthesizerConnection_ = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- }
- public void onServiceDisconnected(ComponentName className) {
- }
- };
-}
diff --git a/android/src/com/levien/synthesizer/android/ui/EffectsActivity.java b/android/src/com/levien/synthesizer/android/ui/EffectsActivity.java
deleted file mode 100644
index 6d0c17f..0000000
--- a/android/src/com/levien/synthesizer/android/ui/EffectsActivity.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.ui;
-
-import android.os.Bundle;
-import com.levien.synthesizer.R;
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
-import com.levien.synthesizer.core.model.composite.Presets.Setting;
-import com.levien.synthesizer.android.widgets.knob.KnobView;
-import com.levien.synthesizer.android.widgets.piano.PianoView;
-
-/**
- * Activity for modifying effects like echo.
- * TODO(klimt): Add the ability to switch channels.
- */
-public class EffectsActivity extends SynthesizerActivity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.effects);
-
- piano_ = (PianoView)findViewById(R.id.piano);
- echoMixKnob_ = (KnobView)findViewById(R.id.echoMixKnob);
- echoDelayKnob_ = (KnobView)findViewById(R.id.echoDelayKnob);
- }
-
- @Override
- protected void onSynthesizerUpdate(MultiChannelSynthesizer synth) {
- int channel = getIntentChannel(this);
- piano_.bindTo(synthesizer_, channel);
- echoMixKnob_.bindTo(synthesizer_, channel, Setting.ECHO_MIX);
- echoDelayKnob_.bindTo(synthesizer_, channel, Setting.ECHO_DELAY);
- }
-
- private PianoView piano_;
- private KnobView echoMixKnob_;
- private KnobView echoDelayKnob_;
-}
diff --git a/android/src/com/levien/synthesizer/android/ui/InstrumentListActivity.java b/android/src/com/levien/synthesizer/android/ui/InstrumentListActivity.java
deleted file mode 100644
index 1941c95..0000000
--- a/android/src/com/levien/synthesizer/android/ui/InstrumentListActivity.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.ui;
-
-import java.util.ArrayList;
-
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
-import com.levien.synthesizer.android.service.SynthesizerService;
-
-import android.app.ListActivity;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.IBinder;
-import android.view.View;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-
-/**
- * An activity that shows the list of available presets (aka instruments), and let's the user click
- * on one of them to begin editing it.
- */
-public class InstrumentListActivity extends ListActivity {
- @Override
- protected void onStart() {
- super.onStart();
- bindService(new Intent(this, SynthesizerService.class),
- synthesizerConnection_, Context.BIND_AUTO_CREATE);
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- unbindService(synthesizerConnection_);
- }
-
- @Override
- protected void onListItemClick(ListView list, View view, int position, long id) {
- this.startActivity(new Intent(null,
- SynthesizerActivity.makeUri(position),
- this,
- EditInstrumentActivity.class));
- }
-
- private ServiceConnection synthesizerConnection_ = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- MultiChannelSynthesizer synthesizer =
- ((SynthesizerService.LocalBinder)service).getSynthesizer();
- ArrayList presets = new ArrayList();
- synthesizer.getPresetNames(presets);
- final ArrayAdapter adapter = new ArrayAdapter(
- InstrumentListActivity.this,
- android.R.layout.simple_list_item_1,
- presets.toArray(new String[0]));
- InstrumentListActivity.this.runOnUiThread(new Runnable() {
- public void run() {
- InstrumentListActivity.this.setListAdapter(adapter);
- InstrumentListActivity.this.getListView().invalidate();
- }
- });
-
- }
- public void onServiceDisconnected(ComponentName className) {
- }
- };
-}
diff --git a/android/src/com/levien/synthesizer/android/ui/KarplusStrongActivity.java b/android/src/com/levien/synthesizer/android/ui/KarplusStrongActivity.java
deleted file mode 100644
index 0ba5ee8..0000000
--- a/android/src/com/levien/synthesizer/android/ui/KarplusStrongActivity.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.ui;
-
-import android.os.Bundle;
-import com.levien.synthesizer.R;
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
-import com.levien.synthesizer.core.model.composite.Presets.Setting;
-import com.levien.synthesizer.android.widgets.knob.KnobView;
-import com.levien.synthesizer.android.widgets.piano.PianoView;
-
-/**
- * Activity for modifying Karplus-Strong parameters.
- * TODO(klimt): Add the ability to switch channels.
- */
-public class KarplusStrongActivity extends SynthesizerActivity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.karplus_strong);
-
- piano_ = (PianoView)findViewById(R.id.piano);
- blendKnob_ = (KnobView)findViewById(R.id.blendKnob);
- stretchKnob_ = (KnobView)findViewById(R.id.stretchKnob);
- excitementKnob_ = (KnobView)findViewById(R.id.excitementKnob);
-
- PianoView piano = (PianoView)findViewById(R.id.piano);
- piano.bindTo(synthesizer_, 0);
- }
-
- @Override
- protected void onSynthesizerUpdate(MultiChannelSynthesizer synth) {
- int channel = getIntentChannel(this);
- Setting[] settings = getIntentSettings(this);
- piano_.bindTo(synthesizer_, channel);
- blendKnob_.bindTo(synthesizer_, channel, settings[0]);
- stretchKnob_.bindTo(synthesizer_, channel, settings[1]);
- excitementKnob_.bindTo(synthesizer_, channel, settings[2]);
- }
-
- private PianoView piano_;
- private KnobView blendKnob_;
- private KnobView stretchKnob_;
- private KnobView excitementKnob_;
-}
diff --git a/android/src/com/levien/synthesizer/android/ui/LowPassFilterActivity.java b/android/src/com/levien/synthesizer/android/ui/LowPassFilterActivity.java
deleted file mode 100644
index d517c0b..0000000
--- a/android/src/com/levien/synthesizer/android/ui/LowPassFilterActivity.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.ui;
-
-import android.os.Bundle;
-import com.levien.synthesizer.R;
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
-import com.levien.synthesizer.core.model.composite.Presets.Setting;
-import com.levien.synthesizer.android.widgets.knob.KnobView;
-import com.levien.synthesizer.android.widgets.piano.PianoView;
-
-/**
- * Activity for modifying low-pass filter settings.
- * TODO(klimt): Add the ability to switch channels.
- */
-public class LowPassFilterActivity extends SynthesizerActivity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.low_pass_filter);
-
- piano_ = (PianoView)findViewById(R.id.piano);
- cutoffKnob_ = (KnobView)findViewById(R.id.cutoffKnob);
- depthKnob_ = (KnobView)findViewById(R.id.depthKnob);
- attackKnob_ = (KnobView)findViewById(R.id.attackKnob);
- decayKnob_ = (KnobView)findViewById(R.id.decayKnob);
- sustainKnob_ = (KnobView)findViewById(R.id.sustainKnob);
- releaseKnob_ = (KnobView)findViewById(R.id.releaseKnob);
-
- PianoView piano = (PianoView)findViewById(R.id.piano);
- piano.bindTo(synthesizer_, 0);
- }
-
- @Override
- protected void onSynthesizerUpdate(MultiChannelSynthesizer synth) {
- int channel = getIntentChannel(this);
- piano_.bindTo(synthesizer_, channel);
- cutoffKnob_.bindTo(synthesizer_, channel, Setting.FILTER_CUTOFF);
- depthKnob_.bindTo(synthesizer_, channel, Setting.FILTER_DEPTH);
- attackKnob_.bindTo(synthesizer_, channel, Setting.FILTER_ATTACK);
- decayKnob_.bindTo(synthesizer_, channel, Setting.FILTER_DECAY);
- sustainKnob_.bindTo(synthesizer_, channel, Setting.FILTER_SUSTAIN);
- releaseKnob_.bindTo(synthesizer_, channel, Setting.FILTER_RELEASE);
- }
-
- private PianoView piano_;
- private KnobView cutoffKnob_;
- private KnobView depthKnob_;
- private KnobView attackKnob_;
- private KnobView decayKnob_;
- private KnobView sustainKnob_;
- private KnobView releaseKnob_;
-}
diff --git a/android/src/com/levien/synthesizer/android/ui/MainActivity.java b/android/src/com/levien/synthesizer/android/ui/MainActivity.java
deleted file mode 100644
index caf802f..0000000
--- a/android/src/com/levien/synthesizer/android/ui/MainActivity.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.ui;
-
-import java.util.ArrayList;
-
-import android.os.Bundle;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemSelectedListener;
-import android.widget.ArrayAdapter;
-import android.widget.Button;
-import android.widget.Spinner;
-
-import com.levien.synthesizer.R;
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
-import com.levien.synthesizer.android.widgets.piano.PianoView;
-
-// TODO(klimt): Add the ability to switch channels.
-
-public class MainActivity extends SynthesizerActivity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
- piano_ = (PianoView)findViewById(R.id.piano);
- presetSpinner_ = (Spinner)findViewById(R.id.presetSpinner);
-
- final Button playButton = (Button)findViewById(R.id.playButton);
- final Button recordButton = (Button)findViewById(R.id.recordButton);
-
- playButton.setOnClickListener(new OnClickListener() {
- public void onClick(View view) {
- if (synthesizer_.getChannel(0).isPlaying()) {
- synthesizer_.getChannel(0).stopPlaying();
- playButton.setText(R.string.play);
- recordButton.setText(R.string.record);
- } else {
- synthesizer_.getChannel(0).startPlaying();
- playButton.setText(R.string.stop);
- recordButton.setText(R.string.record);
- }
- }
- });
-
- recordButton.setOnClickListener(new OnClickListener() {
- public void onClick(View view) {
- if (synthesizer_.getChannel(0).isRecording()) {
- synthesizer_.getChannel(0).stopRecording();
- playButton.setText(R.string.play);
- recordButton.setText(R.string.record);
- } else {
- synthesizer_.getChannel(0).startRecording();
- playButton.setEnabled(true);
- playButton.setText(R.string.play);
- recordButton.setText(R.string.stop);
- }
- }
- });
-
- presetSpinner_.setOnItemSelectedListener(new OnItemSelectedListener() {
- public void onItemSelected(AdapterView> parent, View view, int position, long id) {
- if (synthesizer_ == null) {
- return;
- }
- String preset = presetSpinner_.getItemAtPosition(position).toString();
- if (!preset.equals("")) {
- synthesizer_.getChannel(0).setPreset(preset);
- }
- }
- public void onNothingSelected(AdapterView> parent) {
- }
- });
- }
-
- @Override
- protected void onSynthesizerUpdate(MultiChannelSynthesizer synth) {
- piano_.bindTo(synthesizer_, 0);
-
- ArrayList presetNames = new ArrayList();
- presetNames.add("");
- synthesizer_.getPresetNames(presetNames);
- ArrayAdapter adapter = new ArrayAdapter(
- this, android.R.layout.simple_spinner_item, presetNames);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- presetSpinner_.setAdapter(adapter);
- }
-
- private PianoView piano_;
- private Spinner presetSpinner_;
-}
diff --git a/android/src/com/levien/synthesizer/android/ui/OscillatorActivity.java b/android/src/com/levien/synthesizer/android/ui/OscillatorActivity.java
deleted file mode 100644
index 57eb91f..0000000
--- a/android/src/com/levien/synthesizer/android/ui/OscillatorActivity.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.ui;
-
-import android.os.Bundle;
-import com.levien.synthesizer.R;
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
-import com.levien.synthesizer.core.model.composite.Presets.Setting;
-import com.levien.synthesizer.android.widgets.knob.KnobView;
-import com.levien.synthesizer.android.widgets.piano.PianoView;
-import com.levien.synthesizer.android.widgets.waveform.WaveformRowView;
-
-/**
- * Activity for modifying oscillator parameters.
- * TODO(klimt): Add the ability to switch channels.
- */
-public class OscillatorActivity extends SynthesizerActivity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.oscillator);
-
- piano_ = (PianoView)findViewById(R.id.piano);
- waveformView_ = (WaveformRowView)findViewById(R.id.waveform);
- glideKnob_ = (KnobView)findViewById(R.id.glideKnob);
- coarseKnob_ = (KnobView)findViewById(R.id.coarseKnob);
- fineKnob_ = (KnobView)findViewById(R.id.fineKnob);
- vibratoDepthKnob_ = (KnobView)findViewById(R.id.vibratoDepthKnob);
- balanceKnob_ = (KnobView)findViewById(R.id.balanceKnob);
- }
-
- @Override
- protected void onSynthesizerUpdate(MultiChannelSynthesizer synth) {
- int channel = getIntentChannel(this);
- Setting[] settings = getIntentSettings(this);
- piano_.bindTo(synthesizer_, channel);
- waveformView_.bindTo(synthesizer_, channel, settings[0]);
- glideKnob_.bindTo(synthesizer_, channel, settings[1]);
- coarseKnob_.bindTo(synthesizer_, channel, settings[2]);
- fineKnob_.bindTo(synthesizer_, channel, settings[3]);
- vibratoDepthKnob_.bindTo(synthesizer_, channel, settings[4]);
- balanceKnob_.bindTo(synthesizer_, channel, settings[5]);
- }
-
- private PianoView piano_;
- private WaveformRowView waveformView_;
- private KnobView glideKnob_;
- private KnobView coarseKnob_;
- private KnobView fineKnob_;
- private KnobView vibratoDepthKnob_;
- private KnobView balanceKnob_;
-}
diff --git a/android/src/com/levien/synthesizer/android/ui/PianoActivity.java b/android/src/com/levien/synthesizer/android/ui/PianoActivity.java
deleted file mode 100644
index 2bc6bef..0000000
--- a/android/src/com/levien/synthesizer/android/ui/PianoActivity.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.ui;
-
-import java.util.ArrayList;
-
-import android.os.Bundle;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.Spinner;
-import android.widget.AdapterView.OnItemSelectedListener;
-
-import com.levien.synthesizer.R;
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
-import com.levien.synthesizer.core.model.composite.Presets.Setting;
-import com.levien.synthesizer.android.widgets.knob.KnobView;
-import com.levien.synthesizer.android.widgets.piano.PianoView;
-
-/**
- * Activity for simply playing the piano.
- */
-public class PianoActivity extends SynthesizerActivity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.piano);
-
- piano_ = (PianoView)findViewById(R.id.piano);
- volumeKnob_ = (KnobView)findViewById(R.id.volumeKnob);
- presetSpinner_ = (Spinner)findViewById(R.id.presetSpinner);
-
- presetSpinner_.setOnItemSelectedListener(new OnItemSelectedListener() {
- public void onItemSelected(AdapterView> parent, View view, int position, long id) {
- if (synthesizer_ == null) {
- return;
- }
- if (position > 0) {
- piano_.bindTo(synthesizer_, position - 1);
- volumeKnob_.bindTo(synthesizer_, position - 1, Setting.VOLUME);
- }
- }
- public void onNothingSelected(AdapterView> parent) {
- }
- });
- }
-
- @Override
- protected void onSynthesizerUpdate(MultiChannelSynthesizer synth) {
- piano_.bindTo(synthesizer_, 0);
- volumeKnob_.bindTo(synthesizer_, 0, Setting.VOLUME);
-
- ArrayList presetNames = new ArrayList();
- presetNames.add("");
- synthesizer_.getPresetNames(presetNames);
- ArrayAdapter adapter = new ArrayAdapter(
- this, android.R.layout.simple_spinner_item, presetNames);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- presetSpinner_.setAdapter(adapter);
- }
-
- private PianoView piano_;
- private KnobView volumeKnob_;
- private Spinner presetSpinner_;
-}
diff --git a/android/src/com/levien/synthesizer/android/ui/ScoreActivity.java b/android/src/com/levien/synthesizer/android/ui/ScoreActivity.java
deleted file mode 100644
index a39f130..0000000
--- a/android/src/com/levien/synthesizer/android/ui/ScoreActivity.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.ui;
-
-import java.io.IOException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import android.app.AlertDialog;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-
-import com.levien.synthesizer.R;
-import com.levien.synthesizer.android.Storage;
-import com.levien.synthesizer.android.widgets.score.ScoreView;
-import com.levien.synthesizer.android.widgets.score.ScoreViewToolbar;
-import com.levien.synthesizer.core.midi.MidiListener;
-import com.levien.synthesizer.core.music.Music.Score.Builder;
-
-/**
- * An Activity for editing or playing a score.
- */
-public class ScoreActivity extends SynthActivity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.score);
-
- logger_ = Logger.getLogger(getClass().getName());
-
- scoreView_ = (ScoreView)findViewById(R.id.score);
- scoreViewToolbar_ = (ScoreViewToolbar)findViewById(R.id.toolbar);
-
- scoreViewToolbar_.setScoreView(scoreView_);
- }
-
- @Override
- protected void onStart() {
- super.onStart();
- try {
- Storage.openDefaultScore(scoreView_.getScore(), this.getApplicationContext());
- scoreView_.invalidate();
- scoreViewToolbar_.invalidate();
- } catch (IOException e) {
- logger_.log(Level.SEVERE, "Unable to open score.", e);
- }
- }
-
- @Override
- protected void onStop() {
- try {
- Storage.saveDefaultScore(scoreView_.getScore().build(), this.getApplicationContext());
- } catch (IOException e) {
- logger_.log(Level.SEVERE, "Unable to save score.", e);
- }
- super.onStop();
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.score_menu, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.new_score:
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle("New score...");
- builder.setMessage("This will erase any unsaved work. Are you sure?");
- builder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- scoreView_.getScore().clear();
- scoreView_.invalidate();
- scoreViewToolbar_.invalidate();
- dialog.dismiss();
- }
- });
- builder.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- }
- });
- AlertDialog dialog = builder.create();
- dialog.show();
- return true;
- case R.id.open_score:
- Storage.openScoreWithDialog(scoreView_.getScore(), new Storage.OpenScoreListener() {
- public void onOpenScore(Builder score) {
- scoreView_.invalidate();
- scoreViewToolbar_.invalidate();
- }
- }, this);
- return true;
- case R.id.save_score:
- Storage.saveScoreWithDialog(scoreView_.getScore().build(), this);
- return true;
- case R.id.piano:
- this.startActivity(new Intent(this, PianoActivity.class));
- return true;
- case R.id.chord_grid:
- this.startActivity(new Intent(this, ChordGridActivity.class));
- return true;
- case R.id.edit_instrument:
- this.startActivity(new Intent(this, InstrumentListActivity.class));
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- protected void onSynthConnected() {
- final MidiListener synthMidi = synthesizerService_.getMidiListener();
- scoreView_.bindTo(synthMidi);
- }
-
- private ScoreView scoreView_;
- private ScoreViewToolbar scoreViewToolbar_;
-
- private Logger logger_;
-}
diff --git a/android/src/com/levien/synthesizer/android/ui/SynthesizerActivity.java b/android/src/com/levien/synthesizer/android/ui/SynthesizerActivity.java
deleted file mode 100644
index 06d96eb..0000000
--- a/android/src/com/levien/synthesizer/android/ui/SynthesizerActivity.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.ui;
-
-import android.app.Activity;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.net.Uri;
-import android.os.IBinder;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import com.levien.synthesizer.R;
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
-import com.levien.synthesizer.core.model.composite.Presets.Setting;
-import com.levien.synthesizer.android.service.SynthesizerService;
-
-/**
- * A base class for any Android Activity that wants to interact with the SynthesizerService.
- */
-public abstract class SynthesizerActivity extends Activity {
- /**
- * Called when the synthesizer model changes.
- */
- protected abstract void onSynthesizerUpdate(MultiChannelSynthesizer synth);
-
- /**
- * Creates a URI for a specific synthesizer path.
- * @param path - The absolute path of the component.
- */
- public static Uri makeUri(int channel, Setting... settings) {
- StringBuilder uri = new StringBuilder("content://com.levien.synthesizer/" + channel + "/");
- boolean first = true;
- for (Setting setting : settings) {
- if (!first) {
- uri.append(',');
- }
- uri.append(setting.getNumber());
- first = false;
- }
- return Uri.parse(uri.toString());
- }
-
- /**
- * Returns the path part of the URI that invoked an activity.
- */
- private static String getPath(Activity activity) {
- Intent intent = activity.getIntent();
- if (intent == null) {
- Log.e(SynthesizerActivity.class.getName(),
- "Attempted to get Intent module for SynthesizerActivity with no Intent.");
- return null;
- }
- Uri uri = intent.getData();
- if (uri == null) {
- Log.e(SynthesizerActivity.class.getName(),
- "Attempted to get Intent module for Intent with no URI: " + intent);
- return null;
- }
- String path = uri.getPath();
- if (path == null) {
- Log.e(SynthesizerActivity.class.getName(),
- "Attempted to get Intent module for URI with no path: " + uri);
- return null;
- }
- if (path.startsWith("/")) {
- path = path.substring(1);
- }
- return path;
- }
-
- /**
- * Gets the modules specified by the URI for the intent given to this Activity.
- * @return - The list of settings found, if any. Otherwise, null.
- */
- public static Setting[] getIntentSettings(Activity activity) {
- Setting[] settings = null;
- String path = getPath(activity);
- // Clip off the channel, if it's there...
- if (path.indexOf('/') >= 0) {
- path = path.substring(path.indexOf('/') + 1);
- }
- String[] parts = path.split(", *");
- settings = new Setting[parts.length];
- for (int i = 0; i < parts.length; ++i) {
- try {
- int id = Integer.parseInt(parts[i]);
- settings[i] = Setting.valueOf(id);
- } catch (NumberFormatException e) {
- Log.e(SynthesizerActivity.class.getName(),
- "Unable to convert number \"" + parts[i] + "\" in path: " + path);
- }
- }
- return settings;
- }
-
- /**
- * Gets the channel specified by the URI for the intent given to this Activity.
- * @return - The channel in the intent, or 0 if none was found.
- */
- public static int getIntentChannel(Activity activity) {
- String path = getPath(activity);
- int firstSlash = path.indexOf('/');
- if (firstSlash < 0) {
- Log.e(SynthesizerActivity.class.getName(),
- "Unable to find channel number in path: " + path);
- return 0;
- }
- String channelString = path.substring(0, firstSlash);
- try {
- return Integer.parseInt(channelString);
- } catch (NumberFormatException e) {
- Log.e(SynthesizerActivity.class.getName(),
- "Unable to convert channel number \"" + channelString + "\" in path: " + path);
- return 0;
- }
- }
-
- @Override
- protected void onStart() {
- super.onStart();
- bindService(new Intent(this, SynthesizerService.class),
- synthesizerConnection_, Context.BIND_AUTO_CREATE);
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- unbindService(synthesizerConnection_);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.options_menu, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.piano:
- this.startActivity(new Intent(this, PianoActivity.class));
- return true;
- case R.id.chord_grid:
- this.startActivity(new Intent(this, ChordGridActivity.class));
- return true;
- case R.id.edit_instrument:
- this.startActivity(new Intent(this, InstrumentListActivity.class));
- return true;
- case R.id.compose:
- this.startActivity(new Intent(this, ScoreActivity.class));
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- private ServiceConnection synthesizerConnection_ = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- // synthesizer_ = ISynthesizerService.Stub.asInterface(service);
- synthesizer_ = ((SynthesizerService.LocalBinder)service).getSynthesizer();
- SynthesizerActivity.this.onSynthesizerUpdate(synthesizer_);
- }
- public void onServiceDisconnected(ComponentName className) {
- synthesizer_ = null;
- SynthesizerActivity.this.onSynthesizerUpdate(synthesizer_);
- }
- };
-
- protected MultiChannelSynthesizer synthesizer_ = null;
-}
diff --git a/android/src/com/levien/synthesizer/android/ui/TremoloActivity.java b/android/src/com/levien/synthesizer/android/ui/TremoloActivity.java
deleted file mode 100644
index d5a0060..0000000
--- a/android/src/com/levien/synthesizer/android/ui/TremoloActivity.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.ui;
-
-import android.os.Bundle;
-import com.levien.synthesizer.R;
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
-import com.levien.synthesizer.core.model.composite.Presets.Setting;
-import com.levien.synthesizer.android.widgets.knob.KnobView;
-import com.levien.synthesizer.android.widgets.piano.PianoView;
-import com.levien.synthesizer.android.widgets.waveform.WaveformRowView;
-
-/**
- * Activity for modifying tremolo.
- * TODO(klimt): Add the ability to switch channels.
- */
-public class TremoloActivity extends SynthesizerActivity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.tremolo);
-
- piano_ = (PianoView)findViewById(R.id.piano);
- waveformView_ = (WaveformRowView)findViewById(R.id.waveform);
- rateKnob_ = (KnobView)findViewById(R.id.rateKnob);
- depthKnob_ = (KnobView)findViewById(R.id.depthKnob);
- attackKnob_ = (KnobView)findViewById(R.id.attackKnob);
- decayKnob_ = (KnobView)findViewById(R.id.decayKnob);
- sustainKnob_ = (KnobView)findViewById(R.id.sustainKnob);
- releaseKnob_ = (KnobView)findViewById(R.id.releaseKnob);
- }
-
- @Override
- protected void onSynthesizerUpdate(MultiChannelSynthesizer synth) {
- int channel = getIntentChannel(this);
- piano_.bindTo(synthesizer_, channel);
- waveformView_.bindTo(synthesizer_, channel, Setting.TREMOLO_WAVEFORM);
- rateKnob_.bindTo(synthesizer_, channel, Setting.TREMOLO_RATE);
- depthKnob_.bindTo(synthesizer_, channel, Setting.TREMOLO_DEPTH);
- attackKnob_.bindTo(synthesizer_, channel, Setting.TREMOLO_ATTACK);
- decayKnob_.bindTo(synthesizer_, channel, Setting.TREMOLO_DECAY);
- sustainKnob_.bindTo(synthesizer_, channel, Setting.TREMOLO_SUSTAIN);
- releaseKnob_.bindTo(synthesizer_, channel, Setting.TREMOLO_RELEASE);
- }
-
- private PianoView piano_;
- private WaveformRowView waveformView_;
- private KnobView rateKnob_;
- private KnobView depthKnob_;
- private KnobView attackKnob_;
- private KnobView decayKnob_;
- private KnobView sustainKnob_;
- private KnobView releaseKnob_;
-}
diff --git a/android/src/com/levien/synthesizer/android/ui/VibratoActivity.java b/android/src/com/levien/synthesizer/android/ui/VibratoActivity.java
deleted file mode 100644
index 6c48e50..0000000
--- a/android/src/com/levien/synthesizer/android/ui/VibratoActivity.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.ui;
-
-import android.os.Bundle;
-import com.levien.synthesizer.R;
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
-import com.levien.synthesizer.core.model.composite.Presets.Setting;
-import com.levien.synthesizer.android.widgets.knob.KnobView;
-import com.levien.synthesizer.android.widgets.piano.PianoView;
-import com.levien.synthesizer.android.widgets.waveform.WaveformRowView;
-
-/**
- * Activity for modifying vibrato.
- * TODO(klimt): Add the ability to switch channels.
- */
-public class VibratoActivity extends SynthesizerActivity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.vibrato);
-
- piano_ = (PianoView)findViewById(R.id.piano);
- waveformView_ = (WaveformRowView)findViewById(R.id.waveform);
- rateKnob_ = (KnobView)findViewById(R.id.rateKnob);
- attackKnob_ = (KnobView)findViewById(R.id.attackKnob);
- decayKnob_ = (KnobView)findViewById(R.id.decayKnob);
- sustainKnob_ = (KnobView)findViewById(R.id.sustainKnob);
- releaseKnob_ = (KnobView)findViewById(R.id.releaseKnob);
- }
-
- @Override
- protected void onSynthesizerUpdate(MultiChannelSynthesizer synth) {
- int channel = getIntentChannel(this);
- piano_.bindTo(synthesizer_, channel);
- waveformView_.bindTo(synthesizer_, channel, Setting.VIBRATO_WAVEFORM);
- rateKnob_.bindTo(synthesizer_, channel, Setting.VIBRATO_RATE);
- attackKnob_.bindTo(synthesizer_, channel, Setting.VIBRATO_ATTACK);
- decayKnob_.bindTo(synthesizer_, channel, Setting.VIBRATO_DECAY);
- sustainKnob_.bindTo(synthesizer_, channel, Setting.VIBRATO_SUSTAIN);
- releaseKnob_.bindTo(synthesizer_, channel, Setting.VIBRATO_RELEASE);
- }
-
- private PianoView piano_;
- private WaveformRowView waveformView_;
- private KnobView rateKnob_;
- private KnobView attackKnob_;
- private KnobView decayKnob_;
- private KnobView sustainKnob_;
- private KnobView releaseKnob_;
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/ChordGridView.java b/android/src/com/levien/synthesizer/android/widgets/ChordGridView.java
deleted file mode 100644
index 067893d..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/ChordGridView.java
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets;
-
-import com.levien.synthesizer.R;
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
-import com.levien.synthesizer.core.music.Note;
-import com.levien.synthesizer.android.widgets.piano.PianoViewListener;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Rect;
-import android.graphics.Paint.Style;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-
-/**
- * ChordGridView is an alternative interface for performing that has keys for chords amongst
- * fundamentals arranged in a circle of fifths.
- */
-public class ChordGridView extends View {
- /**
- * Basic android widget constructor.
- */
- public ChordGridView(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- // Get the xml attributes for this instance.
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ChordGridView);
- firstOctave_ = a.getInteger(R.styleable.ChordGridView_octave, 4);
-
- pressedRow_ = -1;
- pressedColumn_ = -1;
-
- drawingRect_ = new Rect();
- path_ = new Path();
- strokePaint_ = new Paint();
- fillPaint_ = new Paint();
- strokePaint_.setStyle(Style.STROKE);
- fillPaint_.setStyle(Style.FILL);
- }
-
- /**
- * Sets the listener that will receive events from this widget.
- */
- public void setPianoViewListener(PianoViewListener pianoViewListener) {
- pianoViewListener_ = pianoViewListener;
- }
-
- /**
- * Signals the listener that a new note was pressed.
- * @param logFrequency - the log frequency of the new note.
- * @param retriggerIfOn - true if this is a new touch, rather than just moving.
- */
- private void notifyNoteDown(double logFrequency, int finger, boolean retriggerIfOn) {
- if (pianoViewListener_ != null) {
- pianoViewListener_.noteDown(logFrequency, finger, retriggerIfOn, 1.0f);
- }
- }
-
- /**
- * Signals the listener that a note was released.
- */
- private void notifyNoteUp(int finger) {
- if (pianoViewListener_ != null) {
- pianoViewListener_.noteUp(finger);
- }
- }
-
- /**
- * Handler for all touch events.
- */
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- int action = event.getAction();
- int actionCode = action & MotionEvent.ACTION_MASK;
- boolean redraw = false;
- if (actionCode == MotionEvent.ACTION_DOWN) {
- int tileWidth = drawingRect_.width() / COLUMNS;
- int tileHeight = drawingRect_.height() / ROWS;
- pressedColumn_ = (int)(event.getX() - drawingRect_.left) / tileWidth;
- pressedRow_ = (int)(event.getY() - drawingRect_.top) / tileHeight;
- redraw = true;
-
- getTileInfo(pressedRow_, pressedColumn_);
- notifyNoteDown(Note.computeLog12TET(tileNote1_, tileOctave1_), 0, true);
- notifyNoteDown(Note.computeLog12TET(tileNote2_, tileOctave2_), 1, true);
- notifyNoteDown(Note.computeLog12TET(tileNote3_, tileOctave3_), 2, true);
- } else if (actionCode == MotionEvent.ACTION_MOVE) {
- int tileWidth = drawingRect_.width() / COLUMNS;
- int tileHeight = drawingRect_.height() / ROWS;
- int newPressedColumn_ = (int)(event.getX() - drawingRect_.left) / tileWidth;
- int newPressedRow_ = (int)(event.getY() - drawingRect_.top) / tileHeight;
- if (pressedColumn_ != newPressedColumn_ || pressedRow_ != newPressedRow_) {
- pressedColumn_ = newPressedColumn_;
- pressedRow_ = newPressedRow_;
- redraw = true;
-
- getTileInfo(pressedRow_, pressedColumn_);
- notifyNoteDown(Note.computeLog12TET(tileNote1_, tileOctave1_), 0, false);
- notifyNoteDown(Note.computeLog12TET(tileNote2_, tileOctave2_), 1, false);
- notifyNoteDown(Note.computeLog12TET(tileNote3_, tileOctave3_), 2, false);
- }
- } else if (actionCode == MotionEvent.ACTION_UP) {
- pressedColumn_ = -1;
- pressedRow_ = -1;
-
- notifyNoteUp(0);
- notifyNoteUp(1);
- notifyNoteUp(2);
- redraw = true;
- } else {
- return super.onTouchEvent(event);
- }
- if (redraw) {
- invalidate();
- }
- return true;
- }
-
- /**
- * Draws the widget.
- */
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- getDrawingRect(drawingRect_);
- int tileWidth = drawingRect_.width() / COLUMNS;
- int tileHeight = drawingRect_.height() / ROWS;
- for (int row = 0; row < ROWS; ++row) {
- for (int column = 0; column < COLUMNS; ++column) {
- getTileInfo(row, column);
- int foreground;
- int background;
- if (Note.isNatural(tileNote1_)) {
- if (row == pressedRow_ && column == pressedColumn_) {
- foreground = Color.GREEN;
- } else {
- foreground = Color.WHITE;
- }
- background = Color.BLACK;
- } else {
- foreground = Color.BLACK;
- if (row == pressedRow_ && column == pressedColumn_) {
- background = Color.GREEN;
- } else {
- background = Color.WHITE;
- }
- }
- int textColor = background;
- fillPaint_.setColor(foreground);
- strokePaint_.setColor(background);
- canvas.drawRect(tileWidth * column,
- tileHeight * row,
- tileWidth * (column + 1),
- tileHeight * (row + 1),
- fillPaint_);
- canvas.drawRect(tileWidth * column + 1,
- tileHeight * row + 1,
- tileWidth * (column + 1) - 2,
- tileHeight * (row + 1) - 2,
- strokePaint_);
- if (tileIsMajor_) {
- textColor = foreground;
- strokePaint_.setColor(foreground);
- fillPaint_.setColor(background);
- path_.reset();
- path_.moveTo(tileWidth * column + 15, tileHeight * (row + 1) - 15);
- path_.lineTo(tileWidth * (column + 1) - 15, tileHeight * (row + 1) - 15);
- path_.lineTo(tileWidth * column + tileWidth / 2, tileHeight * row + 15);
- path_.close();
- canvas.drawPath(path_, fillPaint_);
- }
- if (tileIsMinor_) {
- textColor = foreground;
- strokePaint_.setColor(foreground);
- fillPaint_.setColor(background);
- path_.reset();
- path_.moveTo(tileWidth * column + 15, tileHeight * row + tileHeight / 2);
- path_.lineTo(tileWidth * (column + 1) - 15, tileHeight * (row + 1) - 15);
- path_.lineTo(tileWidth * (column + 1) - 15, tileHeight * row + 15);
- path_.close();
- canvas.drawPath(path_, fillPaint_);
- }
- if (tileNote1_ == Note.C && !tileIsMinor_ && !tileIsMajor_) {
- fillPaint_.setColor(background);
- canvas.drawCircle(tileWidth * column + tileWidth / 2,
- tileHeight * row + tileHeight / 2,
- 10,
- fillPaint_);
- }
- strokePaint_.setColor(textColor);
- canvas.drawText(Note.getName(tileNote1_),
- tileWidth * column + tileWidth / 2,
- tileHeight * row + tileHeight / 2,
- strokePaint_);
- }
- }
- }
-
- /**
- * Populates the tile* fields for the tile at the given row and column.
- */
- private void getTileInfo(int row, int column) {
- int startIndex = 5 + firstOctave_ * 36;
- int absoluteIndex = startIndex + row + column * 14;
- if (absoluteIndex % 3 == 0) {
- // Fundamental key.
- tileOctave1_ = absoluteIndex / 36;
- tileNote1_ = (absoluteIndex % 36) / 3;
- tileOctave2_ = tileOctave1_;
- tileNote2_ = tileNote1_;
- tileOctave3_ = tileOctave1_;
- tileNote3_ = tileNote1_;
- tileIsMajor_ = false;
- tileIsMinor_ = false;
- } else if (absoluteIndex % 3 == 1) {
- // Minor chord key.
- tileOctave3_ = (int)((absoluteIndex - 1) / 36) + 1;
- tileNote3_ = ((absoluteIndex - 1) % 36) / 3;
- if (tileNote3_ >= 4) {
- tileOctave2_ = tileOctave3_;
- tileNote2_ = tileNote3_ - 4;
- } else {
- tileOctave2_ = tileOctave3_ - 1;
- tileNote2_ = tileNote3_ + 8;
- }
- if (tileNote3_ >= 7) {
- tileOctave1_ = tileOctave3_;
- tileNote1_ = tileNote3_ - 7;
- } else {
- tileOctave1_ = tileOctave3_ - 1;
- tileNote1_ = tileNote3_ + 5;
- }
- tileIsMajor_ = false;
- tileIsMinor_ = true;
- } else if (absoluteIndex % 3 == 2) {
- // Major chord key.
- tileOctave1_ = (int)((absoluteIndex + 1) / 36);
- tileNote1_ = ((absoluteIndex + 1) % 36) / 3;
- if (tileNote1_ < 8) {
- tileOctave2_ = tileOctave1_;
- tileNote2_ = tileNote1_ + 4;
- } else {
- tileOctave2_ = tileOctave1_ + 1;
- tileNote2_ = tileNote1_ - 8;
- }
- if (tileNote1_ >= 7) {
- tileOctave3_ = tileOctave1_;
- tileNote3_ = tileNote1_ + 7;
- } else {
- tileOctave3_ = tileOctave1_ + 1;
- tileNote3_ = tileNote1_ - 5;
- }
- tileIsMajor_ = true;
- tileIsMinor_ = false;
- }
- }
-
- /**
- * Connects the ChordGridView to a Synthesizer.
- * @synth - The synthesizer to connect to.
- */
- public void bindTo(final MultiChannelSynthesizer synth, final int channel) {
- this.setPianoViewListener(new PianoViewListener() {
- public void noteDown(double logFrequency, int finger, boolean retriggerIfOn,
- float pressure) {
- synth.getChannel(channel).setPitch(logFrequency, finger);
- synth.getChannel(channel).turnOn(retriggerIfOn, finger);
- }
- public void noteUp(int finger) {
- synth.getChannel(channel).turnOff(finger);
- }
- });
- }
-
- /**
- * Populated by getTileInfo, these fields will contain the info for a particular key.
- */
- private int tileOctave1_;
- private int tileOctave2_;
- private int tileOctave3_;
- private int tileNote1_;
- private int tileNote2_;
- private int tileNote3_;
- private boolean tileIsMajor_;
- private boolean tileIsMinor_;
-
- // The coordinates of the key currently being pressed.
- private int pressedColumn_;
- private int pressedRow_;
-
- // The current octave the keyboard is on.
- private int firstOctave_;
-
- // The listener to receive key events.
- private PianoViewListener pianoViewListener_;
-
- // These are basically stack variables for onDraw. They're member variables only so that we can
- // avoid reallocating them every time the keyboard is redrawn.
- //
- // The most recent screen rect that this keyboard was drawn into.
- private Rect drawingRect_;
- private Path path_;
- private Paint strokePaint_;
- private Paint fillPaint_;
-
- private static final int ROWS = 8;
- private static final int COLUMNS = 5;
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/piano/BlackPianoKey.java b/android/src/com/levien/synthesizer/android/widgets/piano/BlackPianoKey.java
deleted file mode 100644
index d88da27..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/piano/BlackPianoKey.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.piano;
-
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Rect;
-
-import com.levien.synthesizer.core.music.Note;
-
-/**
- * One of the black (non-natural) keys on the piano.
- */
-public class BlackPianoKey extends NotePianoKey {
- /**
- * Creates a new key.
- * @param piano - the piano this key is on.
- * @param octaveOffset - octave of the key, relative to the leftmost octave of the piano.
- * @param key - offset of the key from the start of the octave.
- */
- public BlackPianoKey(PianoView piano, int octave, int key) {
- super(piano, octave, key);
- }
-
- /**
- * Sets rect_ to the position of this key, based on the drawing rect of the piano it's on.
- * @param drawingRect - the position of the piano itself.
- * @param octaves - the number of octaves visible on the piano keyboard.
- */
- public void layout(Rect drawingRect, int octaves) {
- int whiteKeyWidth = getWhiteKeyWidth(drawingRect, octaves);
- int blackKeyWidth = getBlackKeyWidth(drawingRect, octaves);
- rect_.top = 0;
- rect_.bottom = rect_.top + getBlackKeyHeight(drawingRect);
- rect_.left = ((octaveOffset_ * WHITE_KEYS.length + key_ + 2) * whiteKeyWidth) -
- (blackKeyWidth/2);
- rect_.right = rect_.left + blackKeyWidth;
- }
-
- /**
- * Returns the log frequency of the note of the key.
- */
- public double getLogFrequency() {
- return Note.computeLog12TET(BLACK_KEYS[key_], octaveOffset_ + piano_.getFirstOctave());
- }
-
- /**
- * Draws the key in the current rect_.
- */
- public void draw(Canvas canvas) {
- strokePaint_.setColor(Color.BLACK);
- if (isPressed()) {
- fillPaint_.setColor(Color.GREEN);
- } else {
- fillPaint_.setColor(Color.BLACK);
- }
- canvas.drawRect(rect_, fillPaint_);
- canvas.drawRect(rect_, strokePaint_);
- }
-
- /**
- * Returns true if this is one of the black key positions that should actually have a key.
- */
- public static boolean isValid(int note) {
- return BLACK_KEYS[note] != Note.NONE;
- }
-
- /**
- * Utility function to calculate the width that a standard black key on this keyboard should be.
- */
- protected static int getBlackKeyWidth(Rect drawingRect, int octaves) {
- return (getWhiteKeyWidth(drawingRect, octaves) * 2) / 3;
- }
-
- /**
- * Utility function to calculate the height that a standard black key on this keyboard should be.
- */
- protected static int getBlackKeyHeight(Rect drawingRect) {
- return getWhiteKeyHeight(drawingRect) / 2;
- }
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/piano/NotePianoKey.java b/android/src/com/levien/synthesizer/android/widgets/piano/NotePianoKey.java
deleted file mode 100644
index 4980458..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/piano/NotePianoKey.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.piano;
-
-
-/**
- * Abstract base class for keys on the piano that play a note when pressed.
- */
-public abstract class NotePianoKey extends PianoKey {
- /**
- * Creates a new key.
- * @param piano - the piano this key is on.
- * @param octaveOffset - octave of the key, relative to the leftmost octave of the piano.
- * @param key - offset of the key from the start of the octave.
- */
- public NotePianoKey(PianoView piano, int octaveOffset, int key) {
- super(piano);
- octaveOffset_ = octaveOffset;
- key_ = key;
- }
-
- /**
- * Called when the pressed_ state has changed.
- */
- protected void onPressedChanged(boolean move) {
- }
-
- /**
- * Returns the log frequency of the note of the key.
- */
- abstract protected double getLogFrequency();
-
- // Octave of the key, relative to the leftmost octave of the piano.
- protected int octaveOffset_;
-
- // Offset of the key from the start of the octave.
- protected int key_;
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/piano/OctavePianoKey.java b/android/src/com/levien/synthesizer/android/widgets/piano/OctavePianoKey.java
deleted file mode 100644
index fe8c31c..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/piano/OctavePianoKey.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.piano;
-
-
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Path;
-import android.graphics.Rect;
-
-/**
- * A key on the piano for changing the octave up or down.
- */
-public class OctavePianoKey extends PianoKey {
- /**
- * Creates the key.
- * @param piano - the piano this key is on.
- * @param delta - how the octave should change when this key is pressed.
- */
- public OctavePianoKey(PianoView piano, int delta) {
- super(piano);
- arrow_ = new Path();
- delta_ = delta;
- }
-
- /**
- * Sets rect_ to the position of this key, based on the drawing rect of the piano it's on.
- * @param drawingRect - the position of the piano itself.
- * @param octaves - the number of octaves visible on the piano keyboard.
- */
- public void layout(Rect drawingRect, int octaves) {
- int whiteKeyWidth = getWhiteKeyWidth(drawingRect, octaves);
- rect_.top = 0;
- rect_.bottom = getWhiteKeyHeight(drawingRect);
- if (delta_ <= 0) {
- rect_.left = 0;
- rect_.right = rect_.left + whiteKeyWidth;
- } else {
- rect_.right = drawingRect.right;
- rect_.left = rect_.right - whiteKeyWidth;
- }
- }
-
- /**
- * Returns true if the current octave of the piano could be changed by delta and still be valid.
- */
- private boolean isValid() {
- return (piano_.getFirstOctave() + delta_ >= 0 &&
- piano_.getFirstOctave() + piano_.getOctaves() + delta_ <= 8);
- }
-
- /**
- * Draws the key in the current rect_.
- */
- public void draw(Canvas canvas) {
- strokePaint_.setColor(Color.BLACK);
- fillPaint_.setColor(Color.BLACK);
- if (isPressed() && isValid()) {
- fillPaint_.setColor(Color.GREEN);
- }
- canvas.drawRect(rect_, fillPaint_);
- canvas.drawRect(rect_, strokePaint_);
-
- // Draw an arrow in the direction of the delta.
- if (isValid()) {
- arrow_.reset();
- if (delta_ <= 0) {
- arrow_.moveTo(rect_.left + 2, rect_.height() / 2);
- arrow_.lineTo(rect_.right - 2, rect_.height() / 2 - 20);
- arrow_.lineTo(rect_.right - 2, rect_.height() / 2 + 20);
- } else {
- arrow_.moveTo(rect_.right - 2, rect_.height() / 2);
- arrow_.lineTo(rect_.left + 2, rect_.height() / 2 - 20);
- arrow_.lineTo(rect_.left + 2, rect_.height() / 2 + 20);
- }
- arrow_.close();
- fillPaint_.setColor(Color.WHITE);
- canvas.drawPath(arrow_, fillPaint_);
- }
- }
-
- /**
- * Called when the pressed_ state has changed.
- */
- @Override
- protected void onPressedChanged(boolean move) {
- if (isPressed() && isValid()) {
- piano_.changeOctave(delta_);
- }
- }
-
- // This is just used for drawing, but we don't want to pay to reallocate it every time.
- private Path arrow_;
-
- // How the octave should change when this key is pressed.
- private int delta_;
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/piano/PianoKey.java b/android/src/com/levien/synthesizer/android/widgets/piano/PianoKey.java
deleted file mode 100644
index 44e987b..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/piano/PianoKey.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.piano;
-
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.util.Log;
-
-import com.levien.synthesizer.core.music.Note;
-
-/**
- * PianoKey is the abstract base class for any key on the piano.
- * It keeps track of whether the key is currently being pressed.
- */
-public abstract class PianoKey {
- public PianoKey(PianoView piano) {
- piano_ = piano;
- pressed_ = new boolean[PianoView.FINGERS];
- rect_ = new Rect();
-
- for (int i = 0; i < pressed_.length; ++i) {
- pressed_[i] = false;
- }
-
- // Set up some default objects for the key to draw itself with.
- fillPaint_ = new Paint();
- strokePaint_ = new Paint();
- fillPaint_.setStyle(Paint.Style.FILL);
- strokePaint_.setStyle(Paint.Style.STROKE);
- strokePaint_.setColor(Color.BLACK);
- float strokeWidth = 1.0f * piano.getResources().getDisplayMetrics().density;
- strokePaint_.setStrokeWidth(strokeWidth);
- }
-
- /**
- * Sets rect_ to the position of this key, based on the drawing rect of the piano it's on.
- * @param drawingRect - the position of the piano itself.
- * @param octaves - the number of octaves visible on the piano keyboard.
- */
- abstract public void layout(Rect drawingRect, int octaves);
-
- /**
- * Draws the key in the current rect_.
- */
- abstract public void draw(Canvas canvas);
-
- /**
- * Called when the key's pressed_ state has changed.
- * @param move - true if the key became pressed because the touch moved onto it.
- */
- abstract protected void onPressedChanged(boolean move);
-
- /**
- * Returns true if the given co-ordinate is inside the key's current rect_.
- */
- public boolean contains(int x_, int y_) {
- return rect_.contains(x_, y_);
- }
-
- /**
- * Returns true if any finger is pressing this key.
- */
- public boolean isPressed() {
- for (int i = 0; i < pressed_.length; ++i) {
- if (pressed_[i]) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Called when a finger has touched down onto this key.
- * Returns true iff whether the pressed state changed.
- */
- final public boolean onTouchDown(int finger) {
- if (finger >= pressed_.length) {
- Log.e(getClass().getName(),
- "Finger " + finger + " was pressed down, but PianoKey only supports " +
- pressed_.length + " fingers.");
- }
- boolean wasPressed = isPressed();
- pressed_[finger] = true;
- if (!wasPressed) {
- onPressedChanged(false);
- return true;
- }
- return false;
- }
-
- /**
- * Called on a touch event where this key is not being touched. It may already be up.
- * Returns true iff whether the pressed state changed.
- */
- final public boolean onTouchUp(int finger) {
- if (finger >= pressed_.length) {
- Log.e(getClass().getName(),
- "Finger " + finger + " was released, but PianoKey only supports " +
- pressed_.length + " fingers.");
- }
- boolean wasPressed = isPressed();
- pressed_[finger] = false;
- boolean isPressed = isPressed();
- if (wasPressed && !isPressed) {
- onPressedChanged(false);
- return true;
- }
- return false;
- }
-
- /**
- * Called when there's a touch event where the finger was moved onto this key.
- * Returns true iff whether the pressed state changed.
- */
- final public boolean onTouchMoved(int finger) {
- if (finger >= pressed_.length) {
- Log.e(getClass().getName(),
- "Finger " + finger + " was pressed down, but PianoKey only supports " +
- pressed_.length + " fingers.");
- }
- boolean wasPressed = isPressed();
- pressed_[finger] = true;
- if (!wasPressed) {
- onPressedChanged(true);
- return true;
- }
- return false;
- }
-
- /**
- * Utility function to calculate the width that a standard white key on this keyboard should be.
- */
- protected static int getWhiteKeyWidth(Rect drawingRect, int octaves) {
- // It's +2 to reserve space for the octave-up/down buttons.
- return drawingRect.width() / ((WHITE_KEYS.length * octaves) + 2);
- }
-
- /**
- * Utility function to calculate the height that a standard white key on this keyboard should be.
- */
- protected static int getWhiteKeyHeight(Rect drawingRect) {
- return drawingRect.height();
- }
-
- // The piano this key is on.
- protected PianoView piano_;
-
- // Is each keys currently being pressed?
- protected boolean[] pressed_;
-
- // The area this key occupies.
- protected Rect rect_;
-
- // Objects for subclasses to use for painting, just so they don't have to reallocate every time.
- protected Paint fillPaint_;
- protected Paint strokePaint_;
-
- // Constants to map notes onto the keys.
- protected static final int WHITE_KEYS[] = {
- Note.C, Note.D, Note.E, Note.F, Note.G, Note.A, Note.B };
- protected static final int BLACK_KEYS[] = {
- Note.C_SHARP, Note.E_FLAT, Note.NONE, Note.F_SHARP, Note.A_FLAT, Note.B_FLAT, Note.NONE };
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/piano/PianoView.java b/android/src/com/levien/synthesizer/android/widgets/piano/PianoView.java
deleted file mode 100644
index d1b9d62..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/piano/PianoView.java
+++ /dev/null
@@ -1,458 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.piano;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.View;
-
-import com.levien.synthesizer.R;
-import com.levien.synthesizer.core.midi.MidiListener;
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
-import com.levien.synthesizer.core.music.Note;
-
-/**
- * PianoView is a UI widget that simulates a music keyboard.
- */
-public class PianoView extends View {
- /**
- * Basic android widget constructor.
- */
- public PianoView(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- // Get the xml attributes for this instance.
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PianoView);
- octaves_ = a.getInteger(R.styleable.PianoView_octaves, 1);
- firstOctave_ = a.getInteger(R.styleable.PianoView_first_octave, 4);
- a.recycle();
-
- // Set up basic drawing structs, just so we don't have to allocate this later when we draw.
- drawingRect_ = new Rect();
-
- // Generate the set of keys. There are 12 music keys per octave, plus the octave change button
- // on either end.
- keys_ = new PianoKey[12 * octaves_ + 2];
- int key = 0;
-
- // Create the white keys.
- for (int octave = 0; octave < octaves_; ++octave) {
- for (int note = 0; note < 7; ++note) {
- keys_[key++] = new WhitePianoKey(this, octave, note);
- }
- }
-
- // Create the black keys.
- for (int octave = 0; octave < octaves_; ++octave) {
- for (int note = 0; note < 7; ++note) {
- if (BlackPianoKey.isValid(note)) {
- keys_[key++] = new BlackPianoKey(this, octave, note);
- }
- }
- }
-
- // Create the octave changing keys.
- keys_[key++] = new OctavePianoKey(this, -1);
- keys_[key++] = new OctavePianoKey(this, 1);
-
- // The listener will have to be set later.
- pianoViewListener_ = null;
- }
-
- /**
- * Returns the absolute octave of the left-most key.
- */
- public int getFirstOctave() {
- return firstOctave_;
- }
-
- /**
- * Returns the number of octaves covered by all of the keys.
- */
- public int getOctaves() {
- return octaves_;
- }
-
- /**
- * Shifts the octave of all of the keys.
- * @param delta - The number (and direction) of octaves to shift by.
- */
- public void changeOctave(int delta) {
- firstOctave_ += delta;
- }
-
- /**
- * Sets the listener that will receive events from this widget.
- */
- public void setPianoViewListener(PianoViewListener pianoViewListener) {
- pianoViewListener_ = pianoViewListener;
- }
-
- /**
- * Signals the listener that a new note was pressed.
- * @param logFrequency - the log frequency of the new note.
- * @param retriggerIfOn - true if this is a new touch, rather than just moving.
- */
- private void notifyNoteDown(double logFrequency, int finger, boolean retriggerIfOn,
- float pressure) {
- if (pianoViewListener_ != null) {
- pianoViewListener_.noteDown(logFrequency, finger, retriggerIfOn, pressure);
- }
- }
-
- /**
- * Signals the listener that a note was released.
- */
- private void notifyNoteUp(int finger) {
- if (pianoViewListener_ != null) {
- pianoViewListener_.noteUp(finger);
- }
- }
-
- /**
- * Draws the widget.
- */
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- getDrawingRect(drawingRect_);
- for (int i = 0; i < keys_.length; ++i) {
- keys_[i].layout(drawingRect_, octaves_);
- }
- for (int i = 0; i < keys_.length; ++i) {
- keys_[i].draw(canvas);
- }
- }
-
- /**
- * Called to handle touch down events.
- * Returns true iff we need to redraw.
- */
- protected boolean onTouchDown(int finger, int x, int y, float pressure) {
- // Look through keys from top to bottom, and set the first one found as down, the rest as up.
- PianoKey keyDown = null;
- boolean redraw = false;
- for (int i = keys_.length - 1; i >= 0; --i) {
- if (keyDown != null) {
- // If we already found a key that's being touched, then none of the rest can be.
- redraw |= keys_[i].onTouchUp(finger);
- } else if (keys_[i].contains(x, y)) {
- // This key is being touched.
- redraw |= keys_[i].onTouchDown(finger);
- keyDown = keys_[i];
- } else {
- // This key is not being touched.
- redraw |= keys_[i].onTouchUp(finger);
- }
- }
- if (!usePressure_) {
- pressure = 0.5f;
- }
- if (keyDown instanceof NotePianoKey) {
- notifyNoteDown(((NotePianoKey)keyDown).getLogFrequency(), finger, true, pressure);
- }
- return redraw;
- }
-
- /**
- * Called to handle touch move events.
- */
- protected boolean onTouchMove(int finger, int x, int y, float pressure) {
- // Look through keys from top to bottom, and set the first one found as moved, the rest as up.
- PianoKey keyDown = null;
- boolean redraw = false;
- boolean wasPressed = false;
- for (int i = keys_.length - 1; i >= 0; --i) {
- if (keyDown != null) {
- // If we already found a key that's being touched, then none of the rest can be.
- redraw |= keys_[i].onTouchUp(finger);
- } else if (keys_[i].contains(x, y)) {
- // This key is being pressed.
- wasPressed = keys_[i].isPressed();
- redraw |= keys_[i].onTouchMoved(finger);
- keyDown = keys_[i];
- } else {
- // This key is not being pressed.
- redraw |= keys_[i].onTouchUp(finger);
- }
- }
- if (keyDown instanceof NotePianoKey) {
- if (!usePressure_) {
- pressure = 0.5f;
- }
- if (!wasPressed) {
- notifyNoteDown(((NotePianoKey)keyDown).getLogFrequency(), finger, false, pressure);
- }
- } else {
- notifyNoteUp(finger);
- }
- return redraw;
- }
-
- /**
- * Called to handle touch up events.
- */
- protected boolean onTouchUp(int finger) {
- // Set all keys as up.
- boolean redraw = false;
- for (int i = 0; i < keys_.length; ++i) {
- redraw |= keys_[i].onTouchUp(finger);
- }
- notifyNoteUp(finger);
- return redraw;
- }
-
-
- /**
- * Handler for all touch events.
- */
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- int action = event.getAction();
- int actionCode = action & MotionEvent.ACTION_MASK;
- //Log.i("synth", "actionCode = " + actionCode);
- boolean redraw = false;
- if (actionCode == MotionEvent.ACTION_DOWN) {
- int pointerId = event.getPointerId(0);
- if (pointerId < FINGERS) {
- int x = (int)event.getX();
- int y = (int)event.getY();
- float pressure = event.getPressure();
- redraw |= onTouchDown(pointerId, x, y, pressure);
- } else {
- Log.i("synth", "Discarded ACTION_DOWN pointerId=" + pointerId);
- }
- } else if (actionCode == MotionEvent.ACTION_POINTER_DOWN) {
- int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK)
- >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
- int pointerId = event.getPointerId(pointerIndex);
- if (pointerId < FINGERS && pointerId >= 0) {
- int x = (int)event.getX(pointerIndex);
- int y = (int)event.getY(pointerIndex);
- float pressure = event.getPressure(pointerIndex);
- redraw |= onTouchDown(pointerId, x, y, pressure);
- } else {
- Log.i("synth", "Discarded ACTION_POINTER_DOWN pointerId=" + pointerId);
- }
- } else if (actionCode == MotionEvent.ACTION_MOVE) {
- for (int pointerIndex = 0; pointerIndex < event.getPointerCount(); ++pointerIndex) {
- int pointerId = event.getPointerId(pointerIndex);
- if (pointerId >= FINGERS) {
- continue;
- }
- if (pointerIndex >= 0) {
- int x = (int)event.getX(pointerIndex);
- int y = (int)event.getY(pointerIndex);
- float pressure = event.getPressure(pointerIndex);
- redraw |= onTouchMove(pointerId, x, y, pressure);
- }
- }
- } else if (actionCode == MotionEvent.ACTION_UP) {
- int pointerId = event.getPointerId(0);
- if (pointerId < FINGERS) {
- redraw |= onTouchUp(pointerId);
- }
- // Clean up any other pointers that have disappeared.
- for (pointerId = 0; pointerId < FINGERS; ++pointerId) {
- boolean found = false;
- for (int pointerIndex = 0; pointerIndex < event.getPointerCount(); ++pointerIndex) {
- if (pointerId == event.getPointerId(pointerIndex)) {
- found = true;
- break;
- }
- }
- if (!found) {
- boolean thisRedraw = onTouchUp(pointerId);
- if (thisRedraw) {
- Log.i("synth", "ACTION_UP cleaned up pointerId=" + pointerId);
- }
- redraw |= thisRedraw;
- }
- }
- } else if (actionCode == MotionEvent.ACTION_POINTER_UP) {
- int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
- int pointerId = event.getPointerId(pointerIndex);
- if (pointerId < FINGERS) {
- redraw |= onTouchUp(pointerId);
- }
- // Clean up any other pointers that have disappeared. Note: this is probably not necessary.
- for (pointerId = 0; pointerId < FINGERS; ++pointerId) {
- boolean found = false;
- for (pointerIndex = 0; pointerIndex < event.getPointerCount(); ++pointerIndex) {
- if (pointerId == event.getPointerId(pointerIndex)) {
- found = true;
- break;
- }
- }
- if (!found) {
- boolean thisRedraw = onTouchUp(pointerId);
- if (thisRedraw) {
- Log.i("synth", "ACTION_POINTER_UP cleaned up pointerId=" + pointerId);
- }
- redraw |= thisRedraw;
- }
- }
- } else {
- return super.onTouchEvent(event);
- }
- if (redraw) {
- invalidate();
- }
- return true;
- }
-
- /**
- * Layout measurement for this widget.
- * This method just sets a basic minimum size and makes the widget maximized otherwise.
- */
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-
- int width = 0;
- int height = 0;
-
- switch (widthMode) {
- case MeasureSpec.EXACTLY:
- width = widthSize;
- break;
- case MeasureSpec.AT_MOST:
- width = widthSize;
- break;
- case MeasureSpec.UNSPECIFIED:
- width = 10;
- break;
- }
-
- switch (heightMode) {
- case MeasureSpec.EXACTLY:
- height = heightSize;
- break;
- case MeasureSpec.AT_MOST:
- height = heightSize;
- break;
- case MeasureSpec.UNSPECIFIED:
- height = 10;
- break;
- }
-
- setMeasuredDimension(width, height);
- }
-
- /**
- * Connects the PianoView to a Synthesizer.
- * @synth - The synthesizer to connect to.
- * @channel - Which of the synthesizer's channels to bind to.
- */
- public void bindTo(final MultiChannelSynthesizer synth, final int channel) {
- this.setPianoViewListener(new PianoViewListener() {
- public void noteDown(double logFrequency, int finger, boolean retriggerIfOn,
- float pressure) {
- synth.getChannel(channel).setPitch(logFrequency, finger);
- synth.getChannel(channel).turnOn(retriggerIfOn, finger);
- }
- public void noteUp(int finger) {
- synth.getChannel(channel).turnOff(finger);
- }
- });
- }
-
- /**
- * Connects the PianoView to an MidiListener.
- */
- public void bindTo(final MidiListener midiListener) {
- this.setPianoViewListener(new PianoViewListener() {
- {
- fingerMap_ = new HashMap();
- }
- public void noteDown(double logFrequency, int finger, boolean retriggerIfOn,
- float pressure) {
- noteUp(finger);
- int midiNote = Note.getKeyforLog12TET(logFrequency);
- fingerMap_.put(finger, midiNote);
- int midiPressure = Math.max(1, Math.min(127, (int)(127 * pressure)));
- midiListener.onNoteOn(0, midiNote, midiPressure);
- }
- public void noteUp(int finger) {
- if (fingerMap_.containsKey(finger)) {
- int midiNote = fingerMap_.get(finger);
- fingerMap_.remove(finger);
- midiListener.onNoteOff(0, midiNote, 64);
- }
- }
- private Map fingerMap_;
- });
- }
-
- public void setNoteOn(int note, boolean on) {
- // This is somewhat painful, hopefully can be done better.
- for (int i = 0; i < keys_.length; i++) {
- PianoKey key = keys_[i];
- if (key instanceof NotePianoKey) {
- int midiNote = Note.getKeyforLog12TET(((NotePianoKey) key).getLogFrequency());
- if (midiNote == note) {
- boolean redraw;
- if (on) {
- // using the last finger is something of a hack
- redraw = key.onTouchDown(FINGERS - 1);
- } else {
- redraw = key.onTouchUp(FINGERS - 1);
- }
- if (redraw) {
- invalidate();
- }
- break;
- }
- }
- }
- }
-
- // The most recent screen rect that this keyboard was drawn into.
- //
- // This is basically a stack variable for onDraw. It's a member variable only so that we can
- // avoid reallocating them every time the keyboard is redrawn.
- private Rect drawingRect_;
-
- // The set of keys on the keyboard.
- private PianoKey[] keys_;
-
- // The current octave the keyboard is on.
- private int firstOctave_;
-
- // The total number of octaves the keyboard displays at any one time.
- private final int octaves_;
-
- // The listener to receive key events.
- private PianoViewListener pianoViewListener_;
-
- // The number of simultaneous fingers supported by this control.
- protected static final int FINGERS = 10;
-
- // Whether to use pressure (doesn't work well on all hardware)
- private boolean usePressure_ = false;
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/piano/PianoViewListener.java b/android/src/com/levien/synthesizer/android/widgets/piano/PianoViewListener.java
deleted file mode 100644
index 258f422..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/piano/PianoViewListener.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.piano;
-
-// Simple interface for listening to piano widget events.
-public interface PianoViewListener {
- /**
- * A note was pressed.
- * @param logFrequency - the log frequency of the note pressed.
- * @param retriggerIfOn - true if this is a new touch, rather than just moving.
- */
- void noteDown(double logFrequency, int finger, boolean retriggerIfOn, float pressure);
-
- /**
- * The note was released.
- */
- void noteUp(int finger);
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/piano/WhitePianoKey.java b/android/src/com/levien/synthesizer/android/widgets/piano/WhitePianoKey.java
deleted file mode 100644
index 4ab7909..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/piano/WhitePianoKey.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.piano;
-
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Rect;
-
-import com.levien.synthesizer.core.music.Note;
-
-/**
- * A white key on the piano.
- */
-public class WhitePianoKey extends NotePianoKey {
- /**
- * Creates a new key.
- * @param piano - the piano this key is on.
- * @param octaveOffset - octave of the key, relative to the leftmost octave of the piano.
- * @param key - offset of the key from the start of the octave.
- */
- public WhitePianoKey(PianoView piano, int octave, int key) {
- super(piano, octave, key);
- }
-
- /**
- * Sets rect_ to the position of this key, based on the drawing rect of the piano it's on.
- * @param drawingRect - the position of the piano itself.
- * @param octaves - the number of octaves visible on the piano keyboard.
- */
- public void layout(Rect drawingRect, int octaves) {
- int whiteKeyWidth = getWhiteKeyWidth(drawingRect, octaves);
- rect_.top = 0;
- rect_.bottom = getWhiteKeyHeight(drawingRect);
- rect_.left = ((octaveOffset_ * WHITE_KEYS.length + key_ + 1) * whiteKeyWidth);
- rect_.right = rect_.left + whiteKeyWidth;
- }
-
- /**
- * Returns the log frequency of the note of the key.
- */
- public double getLogFrequency() {
- return Note.computeLog12TET(WHITE_KEYS[key_], octaveOffset_ + piano_.getFirstOctave());
- }
-
- /**
- * Draws the key in the current rect_.
- */
- public void draw(Canvas canvas) {
- strokePaint_.setColor(Color.BLACK);
- if (isPressed()) {
- fillPaint_.setColor(Color.GREEN);
- } else {
- fillPaint_.setColor(Color.WHITE);
- }
- canvas.drawRect(rect_, fillPaint_);
- canvas.drawRect(rect_, strokePaint_);
- }
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/score/EditEventTool.java b/android/src/com/levien/synthesizer/android/widgets/score/EditEventTool.java
deleted file mode 100644
index b3ea9e4..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/score/EditEventTool.java
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.score;
-
-import java.util.logging.Logger;
-
-import com.levien.synthesizer.R;
-import com.levien.synthesizer.core.music.Music.Event;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.view.MotionEvent;
-
-/**
- * A tool for editing the events in a score. If the user touches an event, they can move it or
- * resize it. If the event is already selected, all selected events will be moved or resized in the
- * same way. If the user touches outside any events, a selection rectangle allows them to select
- * one or more events.
- */
-public class EditEventTool extends ScoreViewTool {
- /**
- * Creates a new EditEventTool with the given context for loading resources.
- */
- EditEventTool(Context context) {
- logger_ = Logger.getLogger(getClass().getName());
-
- // Set up basic drawing structs, just so we don't have to allocate this later when we draw.
- paint_ = new Paint();
- path_ = new Path();
-
- selection_ = new Rect();
-
- trashVisible_ = false;
- trashRect_ = new Rect();
- trashIcon_ = context.getResources().getDrawable(R.drawable.trash);
-
- icon_ = context.getResources().getDrawable(R.drawable.arrow);
- }
-
- /**
- * Starts this tool editing a particular event, and sets it to invoke another tool when done.
- * Called by NewEventTool to handle sizing the tool as it's being created.
- * @param view - The ScoreView for this tool.
- * @param event - The event to start editing.
- * @param physicalX - The current x of the user's finger, in screen coordinates.
- * @param physicalY -The current y of the user's finger, in screen coordinates.
- * @param nextTool - The tool to select when the user is done editing this event. (on touch up)
- */
- public void pickupEvent(ScoreView view,
- Event.Builder event,
- int physicalX,
- int physicalY,
- ScoreViewTool nextTool) {
- // Save the tool to bring up after this operation is complete.
- nextTool_ = nextTool;
-
- // De-select everything.
- for (int j = 0; j < view.getScore().getEventCount(); ++j) {
- view.getScore().getEventBuilder(j).setSelected(false);
- }
- // Select just the one that was picked up.
- event.setSelected(true);
- mode_ = RESIZING_RIGHT;
-
- // Make sure to snap the event.
- if (!event.hasUnsnappedStart()) {
- event.setUnsnappedStart(event.getStart());
- }
- if (!event.hasUnsnappedEnd()) {
- event.setUnsnappedEnd(event.getEnd());
- }
- if (view.getSnapTo() != 0) {
- event.setStart(((int)(event.getUnsnappedStart() / view.getSnapTo())) * view.getSnapTo());
- event.setEnd(((int)(event.getUnsnappedEnd() / view.getSnapTo())) * view.getSnapTo());
- } else {
- event.setStart(event.getUnsnappedStart());
- event.setEnd(event.getUnsnappedEnd());
- }
-
- // Store the coordinates where it was picked up.
- double time = view.getTimeAt(physicalX);
- double note = view.getNoteAt(physicalY);
- previousTime_ = time;
- previousNote_ = note;
- }
-
- /**
- * Draws the button on the toolbar.
- * @param canvas - The canvas to draw the button on.
- * @param score - The ScoreView that this toolbar is for.
- * @param rect - The area of the button to be drawn, including any margin.
- * @param margin - The preferred margin around the button, in screen coordinates.
- */
- @Override
- public void drawButton(Canvas canvas, ScoreView score, Rect rect, float margin) {
- if (score.getTool() == this) {
- paint_.setColor(Color.WHITE);
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect.left - margin / 2,
- rect.top - margin / 2,
- rect.right + margin / 2,
- rect.bottom + margin / 2,
- paint_);
- }
-
- paint_.setColor(Color.BLACK);
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect, paint_);
- icon_.setBounds(rect);
- icon_.draw(canvas);
- }
-
- /**
- * Called on finger down.
- */
- private void onTouchDown(ScoreView view, int physicalX, int physicalY) {
- double time = view.getTimeAt(physicalX);
- double note = view.getNoteAt(physicalY);
-
- // When we're done editing this item, this tool stays selected.
- nextTool_ = this;
-
- // See if there's an event being touched.
- Event.Builder event = view.getEventAt(physicalX, physicalY);
- if (event != null) {
- if (!event.getSelected()) {
- // De-select everything.
- for (int j = 0; j < view.getScore().getEventCount(); ++j) {
- view.getScore().getEventBuilder(j).setSelected(false);
- }
- // Select just the one that was pressed.
- event.setSelected(true);
- }
-
- // Compute the handle size.
- int physicalHandleSize = view.getNoteY(0) - view.getNoteY(1);
- double handleWidth = view.getTimeAt(physicalHandleSize) - view.getTimeAt(0);
- boolean largeEnough = event.getEnd() - event.getStart() > handleWidth * 2;
-
- // See if any handle was touched.
- if (largeEnough && time <= event.getStart() + handleWidth) {
- mode_ = RESIZING_LEFT;
- } else if (largeEnough && time >= event.getEnd() - handleWidth) {
- mode_ = RESIZING_RIGHT;
- } else {
- mode_ = MOVING;
- }
- } else {
- // De-select everything.
- for (int j = 0; j < view.getScore().getEventCount(); ++j) {
- view.getScore().getEventBuilder(j).setSelected(false);
- }
-
- selection_.left = physicalX;
- selection_.right = physicalX;
- selection_.top = physicalY;
- selection_.bottom = physicalY;
-
- mode_ = SELECTING;
- }
- view.invalidate();
- previousTime_ = time;
- previousNote_ = note;
- }
-
- /**
- * Called on finger movements.
- */
- private void onTouchMove(ScoreView view, int physicalX, int physicalY) {
- double time = view.getTimeAt(physicalX);
- double note = view.getNoteAt(physicalY);
- double deltaTime = time - previousTime_;
- double deltaNote = note - previousNote_;
- switch (mode_) {
- case RESIZING_RIGHT: {
- for (int i = 0; i < view.getScore().getEventCount(); ++i) {
- Event.Builder event = view.getScore().getEventBuilder(i);
- if (!event.getSelected()) {
- continue;
- }
-
- if (!event.hasUnsnappedEnd()) {
- event.setUnsnappedEnd(event.getEnd());
- }
- event.setUnsnappedEnd(event.getUnsnappedEnd() + deltaTime);
- if (view.getSnapTo() != 0) {
- event.setEnd(((int)(event.getUnsnappedEnd() / view.getSnapTo())) * view.getSnapTo());
- } else {
- event.setEnd(event.getUnsnappedEnd());
- }
-
- if (event.getEnd() <= event.getStart()) {
- event.setEnd(event.getStart() + 1/32.0f);
- }
- }
- break;
- }
- case RESIZING_LEFT: {
- for (int i = 0; i < view.getScore().getEventCount(); ++i) {
- Event.Builder event = view.getScore().getEventBuilder(i);
- if (!event.getSelected()) {
- continue;
- }
-
- if (!event.hasUnsnappedStart()) {
- event.setUnsnappedStart(event.getStart());
- }
- event.setUnsnappedStart(event.getUnsnappedStart() + deltaTime);
- if (view.getSnapTo() != 0) {
- event.setStart(((int)(event.getUnsnappedStart() / view.getSnapTo())) * view.getSnapTo());
- } else {
- event.setStart(event.getUnsnappedStart());
- }
-
- if (event.getStart() >= event.getEnd()) {
- event.setEnd(event.getEnd() - 1/32.0f);
- }
- }
- break;
- }
- case MOVING: {
- for (int i = 0; i < view.getScore().getEventCount(); ++i) {
- Event.Builder event = view.getScore().getEventBuilder(i);
- if (!event.getSelected()) {
- continue;
- }
-
- if (!event.hasUnsnappedStart()) {
- event.setUnsnappedStart(event.getStart());
- }
- event.setUnsnappedStart(event.getUnsnappedStart() + deltaTime);
- if (view.getSnapTo() != 0) {
- event.setStart(((int)(event.getUnsnappedStart() / view.getSnapTo())) *
- view.getSnapTo());
- } else {
- event.setStart(event.getUnsnappedStart());
- }
-
- if (!event.hasUnsnappedEnd()) {
- event.setUnsnappedEnd(event.getEnd());
- }
- event.setUnsnappedEnd(event.getUnsnappedEnd() + deltaTime);
- if (view.getSnapTo() != 0) {
- event.setEnd(((int)(event.getUnsnappedEnd() / view.getSnapTo())) * view.getSnapTo());
- } else {
- event.setEnd(event.getUnsnappedEnd());
- }
-
- if (event.getEnd() <= event.getStart()) {
- event.setEnd(event.getStart() + 1/32.0f);
- }
-
- if (!event.hasUnsnappedKey()) {
- event.setUnsnappedKey(event.getKey());
- }
- event.setUnsnappedKey(event.getUnsnappedKey() + deltaNote);
- event.setKey((int)event.getUnsnappedKey());
-
- trashVisible_ = true;
- trashRect_.top = view.getDrawingRect().top;
- trashRect_.bottom = view.getDrawingRect().top +
- Math.max(200, trashIcon_.getIntrinsicHeight());
- trashRect_.left = view.getDrawingRect().right -
- Math.max(200, trashIcon_.getIntrinsicWidth());
- trashRect_.right = view.getDrawingRect().right;
- trashIcon_.setBounds(trashRect_);
- }
- break;
- }
- case SELECTING: {
- // Update the selection rectangle.
- selection_.right = physicalX;
- selection_.bottom = physicalY;
-
- // Update event selections.
- for (int i = 0; i < view.getScore().getEventCount(); ++i) {
- Event.Builder event = view.getScore().getEventBuilder(i);
- if (selection_.intersects(view.getTimeX(event.getStart()),
- view.getNoteY(event.getKey() + 1),
- view.getTimeX(event.getEnd()),
- view.getNoteY(event.getKey()))) {
- view.getScore().getEventBuilder(i).setSelected(true);
- } else {
- view.getScore().getEventBuilder(i).setSelected(false);
- }
- }
-
- break;
- }
- }
- view.invalidate();
- previousTime_ = time;
- previousNote_ = note;
- }
-
- /**
- * Called on finger up.
- */
- private void onTouchUp(ScoreView view, int physicalX, int physicalY) {
- trashVisible_ = false;
-
- if (trashRect_.contains(physicalX, physicalY)) {
- for (int i = view.getScore().getEventCount() - 1; i >= 0; --i) {
- if (view.getScore().getEventBuilder(i).getSelected()) {
- view.getScore().removeEvent(i);
- }
- }
- }
-
- // Make all snapping permanent.
- for (int i = 0; i < view.getScore().getEventCount(); ++i) {
- Event.Builder event = view.getScore().getEventBuilder(i);
- event.clearUnsnappedStart();
- event.clearUnsnappedEnd();
- event.clearUnsnappedKey();
- }
-
- mode_ = NONE;
- view.setTool(nextTool_);
-
- view.invalidate();
- }
-
- /**
- * Called when the user touches the ScoreView while this tool is selected.
- * @param view - The ScoreView that this tool is for.
- * @param event - The touch event that triggered this handler.
- * @return true iff this tool handled the touch event.
- */
- @Override
- public boolean onTouch(ScoreView view, MotionEvent event) {
- int action = event.getAction();
- int actionCode = action & MotionEvent.ACTION_MASK;
- if (actionCode == MotionEvent.ACTION_DOWN) {
- pointerId_ = event.getPointerId(0);
- onTouchDown(view, (int)event.getX(), (int)event.getY());
- return true;
- } else if (actionCode == MotionEvent.ACTION_POINTER_DOWN) {
- return false;
- } else if (actionCode == MotionEvent.ACTION_MOVE) {
- // Find the current positions of the fingers.
- for (int pointerIndex = 0; pointerIndex < event.getPointerCount(); ++pointerIndex) {
- int pointerId = event.getPointerId(pointerIndex);
- if (pointerId >= 0 && pointerId == pointerId_) {
- int physicalX = (int)event.getX(pointerIndex);
- int physicalY = (int)event.getY(pointerIndex);
- onTouchMove(view, physicalX, physicalY);
- return true;
- }
- }
- return false;
- } else if (actionCode == MotionEvent.ACTION_UP) {
- onTouchUp(view, (int)event.getX(), (int)event.getY());
- return true;
- } else if (actionCode == MotionEvent.ACTION_POINTER_UP) {
- return false;
- } else {
- return false;
- }
- }
-
- /**
- * Called after each event is drawn, to give this tool a chance to draw over it.
- * See ScoreView.onDraw() for more information on how ScoreView is drawn.
- * @param event - The event that was drawn.
- * @param canvas - The canvas the key is drawn into.
- * @param rect - The area of the key on the canvas.
- */
- @Override
- public void afterDrawEvent(Event event,
- Canvas canvas,
- Rect rect) {
- if (rect.right >= rect.left + rect.height() * 2) {
- // Draw left arrow.
- float margin = 1.0f;
- paint_.setStrokeWidth(1.0f);
- paint_.setStyle(Paint.Style.STROKE);
- if (event.hasKeyEvent()) {
- paint_.setColor(Color.BLACK);
- } else {
- paint_.setColor(Color.WHITE);
- }
- canvas.drawRect(rect.left, rect.top,
- rect.left + rect.height(), rect.top + rect.height(),
- paint_);
- paint_.setStyle(Paint.Style.FILL);
- path_.reset();
- path_.moveTo(rect.left + rect.height() - margin, rect.top + margin);
- path_.lineTo(rect.left + rect.height() - margin, rect.bottom - margin);
- path_.lineTo(rect.left + margin, (rect.top + rect.bottom) / 2.0f);
- path_.close();
- canvas.drawPath(path_, paint_);
-
- // Draw right arrow.
- paint_.setStyle(Paint.Style.STROKE);
- if (event.hasKeyEvent()) {
- paint_.setColor(Color.BLACK);
- } else {
- paint_.setColor(Color.WHITE);
- }
- canvas.drawRect(rect.right - rect.height(), rect.top, rect.right, rect.bottom, paint_);
- paint_.setStyle(Paint.Style.FILL);
- path_.reset();
- path_.moveTo(rect.right - (rect.height() - (margin + 1)), rect.top + margin);
- path_.lineTo(rect.right - (rect.height() - (margin + 1)), rect.bottom - margin);
- path_.lineTo(rect.right - margin, (rect.top + rect.bottom) / 2.0f);
- path_.close();
- canvas.drawPath(path_, paint_);
- }
- }
-
- /**
- * Called after the entire score is drawn, to give this tool a chance to draw over it.
- * Draws the selection box, and possibly the trash icon.
- * See ScoreView.onDraw() for more information on how ScoreView is drawn.
- * @param view - The ScoreView being drawn.
- * @param canvas - The canvas the key is drawn into.
- * @param rect - The area of the key on the canvas.
- */
- @Override
- public void afterDrawScore(ScoreView view, Canvas canvas, Rect rect) {
- if (mode_ == SELECTING) {
- paint_.setStyle(Paint.Style.FILL);
- paint_.setColor(Color.CYAN);
- paint_.setAlpha(127);
- canvas.drawRect(selection_, paint_);
- paint_.setAlpha(255);
- }
-
- // Draw the trash can.
- if (trashVisible_) {
- trashIcon_.draw(canvas);
- }
- }
-
- // The id of the finger doing the editing.
- private int pointerId_;
-
- // The most recent previous position of the finger.
- private double previousTime_;
- private double previousNote_;
-
- // A tool to select the next time the user finishes editing an event.
- // Can be "this", but not null.
- private ScoreViewTool nextTool_;
-
- // While the user is drawing a selection rectangle, this is it, in screen (physical) coordinates.
- private Rect selection_;
-
- // Some objects used in drawing. They are owned here so that they don't have to be reallocated
- // and garbage collected for every pass of drawing.
- protected Paint paint_;
- protected Path path_;
- private Drawable icon_;
-
- // The mode of the tool, depending mostly on where the user's finger was when they first touched.
- private int mode_;
- private static final int NONE = 0;
- private static final int RESIZING_LEFT = 1;
- private static final int RESIZING_RIGHT = 2;
- private static final int MOVING = 3;
- private static final int SELECTING = 4;
-
- // Members for controlling how the trash can icon gets drawn while moving events.
- private boolean trashVisible_;
- private Rect trashRect_; // in screen (physical) coordinates.
- private Drawable trashIcon_;
-
- @SuppressWarnings("unused")
- private Logger logger_;
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/score/HideChannelButton.java b/android/src/com/levien/synthesizer/android/widgets/score/HideChannelButton.java
deleted file mode 100644
index b8bd815..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/score/HideChannelButton.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.score;
-
-import java.util.logging.Logger;
-
-import com.levien.synthesizer.R;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-
-/**
- * A button that toggles between showing the events for all of the synthesizer channels or showing
- * just the currently selected channel.
- */
-public class HideChannelButton extends ScoreViewTool {
- /**
- * Creates a new HideChannelButton, using the given context for loading resources.
- */
- HideChannelButton(Context context) {
- logger_ = Logger.getLogger(getClass().getName());
-
- visibleIcon_ = context.getResources().getDrawable(R.drawable.open_eye);
- hiddenIcon_ = context.getResources().getDrawable(R.drawable.closed_eye);
- paint_ = new Paint();
- }
-
- /**
- * Called when this tool is selected.
- * Changes the channel visibility and then reselects the previous tool.
- * @param view - The ScoreView that this toolbar is for.
- * @param previousTool - The tool that was selected when this one was chosen.
- */
- @Override
- public void onSelect(ScoreView view, ScoreViewTool previousTool) {
- view.setOtherChannelsVisible(!view.getOtherChannelsVisible());
- view.setTool(previousTool);
- }
-
- /**
- * Draws the button on the toolbar.
- * @param canvas - The canvas to draw the button on.
- * @param score - The ScoreView that this toolbar is for.
- * @param rect - The area of the button to be drawn, including any margin.
- * @param margin - The preferred margin around the button, in screen coordinates.
- */
- @Override
- public void drawButton(Canvas canvas, ScoreView score, Rect rect, float margin) {
- if (score.getTool() == this) {
- paint_.setColor(Color.WHITE);
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect.left - margin / 2,
- rect.top - margin / 2,
- rect.right + margin / 2,
- rect.bottom + margin / 2,
- paint_);
- }
-
- paint_.setColor(Color.BLACK);
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect, paint_);
- if (score.getOtherChannelsVisible()) {
- visibleIcon_.setBounds(rect);
- visibleIcon_.draw(canvas);
- } else {
- hiddenIcon_.setBounds(rect);
- hiddenIcon_.draw(canvas);
- }
- }
-
- // Some objects used in drawing. They are owned here so that they don't have to be reallocated
- // and garbage collected for every pass of drawing.
- private Paint paint_;
- private Drawable visibleIcon_;
- private Drawable hiddenIcon_;
-
- @SuppressWarnings("unused")
- private Logger logger_;
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/score/NewEventTool.java b/android/src/com/levien/synthesizer/android/widgets/score/NewEventTool.java
deleted file mode 100644
index 3179a23..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/score/NewEventTool.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.score;
-
-import java.util.logging.Logger;
-
-import com.levien.synthesizer.R;
-import com.levien.synthesizer.core.music.Music.Event;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.view.MotionEvent;
-
-/**
- * A tool for creating new events in the score.
- */
-public class NewEventTool extends ScoreViewTool {
- /**
- * Creates a new NewEventTool.
- * @param context - The context to use for loading resources.
- * @param eventTool - The tool to use for editing the event as it's created.
- */
- NewEventTool(Context context, EditEventTool eventTool) {
- logger_ = Logger.getLogger(getClass().getName());
- eventTool_ = eventTool;
-
- icon_ = context.getResources().getDrawable(R.drawable.add);
- paint_ = new Paint();
- }
-
- /**
- * Draws the button on the toolbar.
- * @param canvas - The canvas to draw the button on.
- * @param score - The ScoreView that this toolbar is for.
- * @param rect - The area of the button to be drawn, including any margin.
- * @param margin - The preferred margin around the button, in screen coordinates.
- */
- @Override
- public void drawButton(Canvas canvas, ScoreView score, Rect rect, float margin) {
- if (score.getTool() == this) {
- paint_.setColor(Color.WHITE);
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect.left - margin / 2,
- rect.top - margin / 2,
- rect.right + margin / 2,
- rect.bottom + margin / 2,
- paint_);
- }
-
- paint_.setColor(Color.BLACK);
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect, paint_);
- icon_.setBounds(rect);
- icon_.draw(canvas);
- }
-
- /**
- * Called when the user touches the ScoreView while this tool is selected.
- * @param view - The ScoreView that this tool is for.
- * @param event - The touch event that triggered this handler.
- * @return true iff this tool handled the touch event.
- */
- @Override
- public boolean onTouch(ScoreView view, MotionEvent event) {
- int action = event.getAction();
- int actionCode = action & MotionEvent.ACTION_MASK;
- if (actionCode == MotionEvent.ACTION_DOWN) {
- double time = view.getTimeAt((int)event.getX());
- double note = view.getNoteAt((int)event.getY());
-
- if (view.getSnapTo() != 0) {
- time = ((int)(time / view.getSnapTo())) * view.getSnapTo();
- }
-
- Event.Builder e = view.getScore().addEventBuilder();
- e.setStart(time);
- e.setEnd(time + view.getSnapTo());
- e.setKey((int)note);
- e.getKeyEventBuilder().setChannel(view.getCurrentChannel());
-
- eventTool_.pickupEvent(view, e, (int)event.getX(), (int)event.getY(), this);
- view.setTool(eventTool_);
- return true;
- } else {
- return false;
- }
- }
-
- // The tool that's used to edit the event after it's created, but only until the finger is up.
- // Then control returns back to this control.
- private EditEventTool eventTool_;
-
- // Some objects used in drawing. They are owned here so that they don't have to be reallocated
- // and garbage collected for every pass of drawing.
- private Paint paint_;
- private Drawable icon_;
-
- @SuppressWarnings("unused")
- private Logger logger_;
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/score/NewLoopTool.java b/android/src/com/levien/synthesizer/android/widgets/score/NewLoopTool.java
deleted file mode 100644
index 9df4e91..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/score/NewLoopTool.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.score;
-
-import java.util.logging.Logger;
-
-import com.levien.synthesizer.R;
-import com.levien.synthesizer.core.music.Music.Event;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.view.MotionEvent;
-
-/**
- * A tool for creating new events in the score.
- */
-public class NewLoopTool extends ScoreViewTool {
- /**
- * Creates a new NewEventTool.
- * @param context - The context to use for loading resources.
- * @param eventTool - The tool to use for editing the event as it's created.
- */
- NewLoopTool(Context context, EditEventTool eventTool) {
- logger_ = Logger.getLogger(getClass().getName());
- eventTool_ = eventTool;
-
- icon_ = context.getResources().getDrawable(R.drawable.loop);
- paint_ = new Paint();
- }
-
- /**
- * Draws the button on the toolbar.
- * @param canvas - The canvas to draw the button on.
- * @param score - The ScoreView that this toolbar is for.
- * @param rect - The area of the button to be drawn, including any margin.
- * @param margin - The preferred margin around the button, in screen coordinates.
- */
- @Override
- public void drawButton(Canvas canvas, ScoreView score, Rect rect, float margin) {
- if (score.getTool() == this) {
- paint_.setColor(Color.WHITE);
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect.left - margin / 2,
- rect.top - margin / 2,
- rect.right + margin / 2,
- rect.bottom + margin / 2,
- paint_);
- }
-
- paint_.setColor(Color.BLACK);
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect, paint_);
- icon_.setBounds(rect);
- icon_.draw(canvas);
- }
-
- /**
- * Called when the user touches the ScoreView while this tool is selected.
- * @param view - The ScoreView that this tool is for.
- * @param event - The touch event that triggered this handler.
- * @return true iff this tool handled the touch event.
- */
- @Override
- public boolean onTouch(ScoreView view, MotionEvent event) {
- int action = event.getAction();
- int actionCode = action & MotionEvent.ACTION_MASK;
- if (actionCode == MotionEvent.ACTION_DOWN) {
- double time = view.getTimeAt((int)event.getX());
- double note = view.getNoteAt((int)event.getY());
-
- if (view.getSnapTo() != 0) {
- time = ((int)(time / view.getSnapTo())) * view.getSnapTo();
- }
-
- Event.Builder e = view.getScore().addEventBuilder();
- e.setStart(time);
- e.setEnd(time + view.getSnapTo());
- e.setKey((int)note);
- e.getLoopEventBuilder().setCount(1);
-
- eventTool_.pickupEvent(view, e, (int)event.getX(), (int)event.getY(), this);
- view.setTool(eventTool_);
- return true;
- } else {
- return false;
- }
- }
-
- // The tool that's used to edit the event after it's created, but only until the finger is up.
- // Then control returns back to this control.
- private EditEventTool eventTool_;
-
- // Some objects used in drawing. They are owned here so that they don't have to be reallocated
- // and garbage collected for every pass of drawing.
- private Paint paint_;
- private Drawable icon_;
-
- @SuppressWarnings("unused")
- private Logger logger_;
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/score/PlayButton.java b/android/src/com/levien/synthesizer/android/widgets/score/PlayButton.java
deleted file mode 100644
index 594aa3c..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/score/PlayButton.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.score;
-
-import java.util.logging.Logger;
-
-import com.levien.synthesizer.R;
-import com.levien.synthesizer.core.music.ScorePlayer;
-import com.levien.synthesizer.core.music.ScorePlayerListener;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-
-/**
- * A button to start the current score playing.
- */
-public class PlayButton extends ScoreViewTool implements ScorePlayerListener {
- /**
- * Creates a new play button, loading resources from the given context.
- */
- PlayButton(ScoreViewToolbar toolbar, Context context) {
- toolbar_ = toolbar;
- logger_ = Logger.getLogger(getClass().getName());
- player_ = new ScorePlayer();
-
- playing_ = false;
-
- playingIcon_ = context.getResources().getDrawable(R.drawable.stop);
- stoppedIcon_ = context.getResources().getDrawable(R.drawable.play);
- paint_ = new Paint();
- }
-
- /**
- * Called when this tool is selected. Starts the score playing.
- * @param view - The ScoreView that this toolbar is for.
- * @param previousTool - The tool that was selected when this one was chosen.
- */
- @Override
- public void onSelect(ScoreView view, ScoreViewTool previousTool) {
- view_ = view;
- if (playing_) {
- player_.stopPlaying();
- } else {
- player_.startPlaying(view.getSynthesizer(), view.getScore().build(), 120.0, 4, this);
- }
- view.setTool(previousTool);
- }
-
- /**
- * Draws the button on the toolbar.
- * @param canvas - The canvas to draw the button on.
- * @param score - The ScoreView that this toolbar is for.
- * @param rect - The area of the button to be drawn, including any margin.
- * @param margin - The preferred margin around the button, in screen coordinates.
- */
- @Override
- public void drawButton(Canvas canvas, ScoreView score, Rect rect, float margin) {
- if (score.getTool() == this) {
- paint_.setColor(Color.WHITE);
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect.left - margin / 2,
- rect.top - margin / 2,
- rect.right + margin / 2,
- rect.bottom + margin / 2,
- paint_);
- }
-
- paint_.setColor(Color.BLACK);
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect, paint_);
-
- if (playing_) {
- playingIcon_.setBounds(rect);
- playingIcon_.draw(canvas);
- } else {
- stoppedIcon_.setBounds(rect);
- stoppedIcon_.draw(canvas);
- }
- }
-
- /**
- * Called when the score starts playing.
- */
- public void onStart() {
- view_.post(new Thread("PlayButton.onStart()") {
- public void run() {
- playing_ = true;
- view_.invalidate();
- toolbar_.invalidate();
- }
- });
- }
-
- /**
- * Called every so often during playback.
- * @param time - the time in measures from the start of the song.
- */
- public void onTimeUpdate(final double time) {
- view_.post(new Thread("PlayButton.onTimeUpdate()") {
- public void run() {
- view_.setCursor(time);
- view_.invalidate();
- toolbar_.invalidate();
- }
- });
- }
-
- /**
- * Called when the score stops playing.
- */
- public void onStop() {
- view_.post(new Thread("PlayButton.onStop()") {
- public void run() {
- playing_ = false;
- view_.invalidate();
- }
- });
- }
-
- // The ScoreView that this button controls.
- private ScoreView view_;
- private ScoreViewToolbar toolbar_;
-
- // ScorePlayer to play the score.
- private ScorePlayer player_;
-
- // Is the score playing?
- private boolean playing_;
-
- // Some objects used in drawing. They are owned here so that they don't have to be reallocated
- // and garbage collected for every pass of drawing.
- private Paint paint_;
- private Drawable playingIcon_;
- private Drawable stoppedIcon_;
-
- @SuppressWarnings("unused")
- private Logger logger_;
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/score/PlayTool.java b/android/src/com/levien/synthesizer/android/widgets/score/PlayTool.java
deleted file mode 100644
index 7ff5dc8..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/score/PlayTool.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.score;
-
-import java.util.logging.Logger;
-
-import com.levien.synthesizer.R;
-import com.levien.synthesizer.core.music.Note;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.view.MotionEvent;
-
-/**
- * A button to enable "play" mode of the ScoreView. In play mode, pressing anywhere plays the note
- * for the key that's being pressed. @see ScoreView.
- */
-public class PlayTool extends ScoreViewTool {
- /**
- * Creates a new PlayTool, loading resources from the given context.
- */
- PlayTool(Context context) {
- logger_ = Logger.getLogger(getClass().getName());
-
- keysDown_ = new int[FINGERS];
- for (int i = 0; i < keysDown_.length; ++i) {
- keysDown_[i] = -1;
- }
-
- icon_ = context.getResources().getDrawable(R.drawable.play_piano);
- paint_ = new Paint();
- }
-
- /**
- * Draws the button on the toolbar.
- * @param canvas - The canvas to draw the button on.
- * @param score - The ScoreView that this toolbar is for.
- * @param rect - The area of the button to be drawn, including any margin.
- * @param margin - The preferred margin around the button, in screen coordinates.
- */
- @Override
- public void drawButton(Canvas canvas, ScoreView score, Rect rect, float margin) {
- if (score.getTool() == this) {
- paint_.setColor(Color.WHITE);
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect.left - margin / 2,
- rect.top - margin / 2,
- rect.right + margin / 2,
- rect.bottom + margin / 2,
- paint_);
- }
-
- paint_.setColor(Color.BLACK);
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect, paint_);
- icon_.setBounds(rect);
- icon_.draw(canvas);
- }
-
- /**
- * Called after each key is drawn, to give this tool a chance to draw over it.
- * See ScoreView.onDraw() for more information on how ScoreView is drawn.
- * @param key - The key that was drawn.
- * @param canvas - The canvas the key is drawn into.
- * @param rect - The area of the key on the canvas.
- */
- @Override
- public void afterDrawKey(int key,
- Canvas canvas,
- Rect rect) {
- for (int keyDown : keysDown_) {
- if (key == keyDown) {
- paint_.setColor(Color.GREEN);
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect, paint_);
- }
- }
- }
-
- /**
- * Called to handle touch down events.
- * Returns true iff we need to redraw.
- */
- private boolean onTouchDown(ScoreView view, int finger, int physicalX, int physicalY) {
- int note = (int)Math.floor(view.getNoteAt(physicalY));
- view.getSynthesizer().onNoteOn(view.getCurrentChannel(), note, 64);
- keysDown_[finger] = note;
- return true;
- }
-
- /**
- * Called to handle touch move events.
- */
- private boolean onTouchMove(ScoreView view, int finger, int physicalX, int physicalY) {
- int note = (int)Math.floor(view.getNoteAt(physicalY));
- int oldNote = keysDown_[finger];
- if (oldNote >= 0) {
- view.getSynthesizer().onNoteOff(view.getCurrentChannel(), oldNote, 64);
- }
- view.getSynthesizer().onNoteOn(view.getCurrentChannel(), note, 64);
- keysDown_[finger] = (int)note;
- return true;
- }
-
- /**
- * Called to handle touch up events.
- */
- protected boolean onTouchUp(ScoreView view, int finger) {
- int note = keysDown_[finger];
- view.getSynthesizer().onNoteOff(view.getCurrentChannel(), note, 64);
- keysDown_[finger] = -1;
- return true;
- }
-
- /**
- * Called when the user touches the ScoreView while this tool is selected.
- * @param view - The ScoreView that this tool is for.
- * @param event - The touch event that triggered this handler.
- * @return true iff this tool handled the touch event.
- */
- @Override
- public boolean onTouch(ScoreView view, MotionEvent event) {
- int action = event.getAction();
- int actionCode = action & MotionEvent.ACTION_MASK;
- boolean redraw = false;
- if (actionCode == MotionEvent.ACTION_DOWN) {
- int pointerId = event.getPointerId(0);
- if (pointerId < FINGERS) {
- int x = (int)event.getX();
- int y = (int)event.getY();
- redraw |= onTouchDown(view, pointerId, x, y);
- }
- } else if (actionCode == MotionEvent.ACTION_POINTER_DOWN) {
- int pointerId = action >> MotionEvent.ACTION_POINTER_ID_SHIFT;
- if (pointerId < FINGERS) {
- int pointerIndex = event.findPointerIndex(pointerId);
- if (pointerIndex >= 0) {
- int x = (int)event.getX(pointerIndex);
- int y = (int)event.getY(pointerIndex);
- redraw |= onTouchDown(view, pointerId, x, y);
- }
- }
- } else if (actionCode == MotionEvent.ACTION_MOVE) {
- for (int pointerIndex = 0; pointerIndex < event.getPointerCount(); ++pointerIndex) {
- int pointerId = event.getPointerId(pointerIndex);
- if (pointerId >= FINGERS) {
- continue;
- }
- if (pointerIndex >= 0) {
- int x = (int)event.getX(pointerIndex);
- int y = (int)event.getY(pointerIndex);
- redraw |= onTouchMove(view, pointerId, x, y);
- }
- }
- } else if (actionCode == MotionEvent.ACTION_UP) {
- int pointerId = event.getPointerId(0);
- if (pointerId < FINGERS) {
- redraw |= onTouchUp(view, pointerId);
- }
- // Clean up any other pointers that have disappeared.
- for (pointerId = 0; pointerId < FINGERS; ++pointerId) {
- boolean found = false;
- for (int pointerIndex = 0; pointerIndex < event.getPointerCount(); ++pointerIndex) {
- if (pointerId == event.getPointerId(pointerIndex)) {
- found = true;
- break;
- }
- }
- if (!found) {
- redraw |= onTouchUp(view, pointerId);
- }
- }
- } else if (actionCode == MotionEvent.ACTION_POINTER_UP) {
- int pointerId = action >> MotionEvent.ACTION_POINTER_ID_SHIFT;
- if (pointerId < FINGERS) {
- redraw |= onTouchUp(view, pointerId);
- }
- // Clean up any other pointers that have disappeared.
- for (pointerId = 0; pointerId < FINGERS; ++pointerId) {
- boolean found = false;
- for (int pointerIndex = 0; pointerIndex < event.getPointerCount(); ++pointerIndex) {
- if (pointerId == event.getPointerId(pointerIndex)) {
- found = true;
- break;
- }
- }
- if (!found) {
- redraw |= onTouchUp(view, pointerId);
- }
- }
- } else {
- return false;
- }
- if (redraw) {
- view.invalidate();
- }
- return true;
- }
-
- // The piano key each finger is holding down, or -1 if a finger is not pressing any key.
- private int[] keysDown_;
-
- // Some objects used in drawing. They are owned here so that they don't have to be reallocated
- // and garbage collected for every pass of drawing.
- private Paint paint_;
- private Drawable icon_;
-
- // The number of simultaneous fingers supported by this control.
- protected static final int FINGERS = 5;
-
- @SuppressWarnings("unused")
- private Logger logger_;
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/score/ScoreView.java b/android/src/com/levien/synthesizer/android/widgets/score/ScoreView.java
deleted file mode 100644
index 1d8ea5a..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/score/ScoreView.java
+++ /dev/null
@@ -1,767 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.score;
-
-import java.util.logging.Logger;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-
-import com.levien.synthesizer.R;
-import com.levien.synthesizer.core.midi.MidiListener;
-import com.levien.synthesizer.core.music.Music.Event;
-import com.levien.synthesizer.core.music.Music.Score;
-import com.levien.synthesizer.core.music.Note;
-
-/**
- * ScoreView is a UI widget that allows editing a musical score, as well as live playing. The
- * majority of the ScoreView area shows a subsequence of the current musical score. Along the
- * y-axis are the keys of a piano. Time is along the x-axis. Along the bottom, there is a toolbar,
- * which allows selecting various "tools" to use on the score.
- *
- * A score is composed of various "events", such as playing a note for a certain duration at a
- * certain time, using a certain channel. A ScoreView lets the user create or edit these events.
- *
- * PlayTool - When selected, pressing plays the note at that x using the selected channel.
- * ViewportTool - Sets the currently visible part of the score by touching or dragging.
- * NewEventTool - Creates new events.
- * EditEventTool - Edits an existing event.
- * PlayButton - Starts the score playing audibly.
- * SelectChannelButton - Selects a particular channel (instrument) for editing or playing.
- * HideChannelButton - Toggles whether to show/hide the channels not currently being edited.
- * SnapTool - Changes the "snap to" setting for this ScoreView.
- */
-public class ScoreView extends View {
- /**
- * Basic android widget constructor.
- */
- public ScoreView(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- logger_ = Logger.getLogger(getClass().getName());
-
- // Set the default time to be 20 measures, and show 5 measures to start.
- minTime_ = 0.0;
- maxTime_ = 20.0;
- timeZoom_ = 0.25;
- timeOffset_ = 0.0;
-
- // Set the piano keys to the range of a normal piano, showing one octave to start.
- minNote_ = Note.A;
- maxNote_ = Note.A + 88.0;
- noteZoom_ = 8.0 / 88.0;
- noteOffset_ = 44.0;
-
- // Snap to eighth notes to start.
- snapTo_ = 1.0 / 8.0;
-
- // Create the score to edit.
- score_ = Score.newBuilder();
-
- // Setup the channels.
- currentChannel_ = 0;
- showOtherChannels_ = true;
-
- // Load the icon to use for each channel.
- iconForChannel_ = new Drawable[CHANNELS];
- iconForChannel_[0] = context.getResources().getDrawable(R.drawable.guitar);
- iconForChannel_[1] = context.getResources().getDrawable(R.drawable.bass);
- iconForChannel_[2] = context.getResources().getDrawable(R.drawable.voice);
- iconForChannel_[3] = context.getResources().getDrawable(R.drawable.flute);
- iconForChannel_[4] = context.getResources().getDrawable(R.drawable.drums);
-
- arrowsVisible_ = true;
- upSelected_ = false;
- downSelected_ = false;
- upIcon_ = context.getResources().getDrawable(R.drawable.up);
- downIcon_ = context.getResources().getDrawable(R.drawable.down);
-
- // Set up basic drawing structs, just so we don't have to allocate them later when we draw.
- drawingRect_ = new Rect();
- keyRect_ = new Rect();
- eventRect_ = new Rect();
- fillPaint_ = new Paint();
- strokePaint_ = new Paint();
- marginPaint_ = new Paint();
-
- fillPaint_.setStyle(Paint.Style.FILL);
- strokePaint_.setStyle(Paint.Style.STROKE);
- marginPaint_.setStyle(Paint.Style.FILL);
- marginPaint_.setColor(Color.GRAY);
- }
-
- /**
- * Returns a mutable copy of the score being edited.
- */
- public Score.Builder getScore() {
- return score_;
- }
-
- /**
- * Returns the currently selected channel (instrument).
- */
- public int getCurrentChannel() {
- return currentChannel_;
- }
-
- /**
- * Selects the given channel.
- * @param channel - The channel to select.
- */
- public void setCurrentChannel(int channel) {
- currentChannel_ = channel;
- }
-
- /**
- * Returns true iff the given channel is visible in the score.
- */
- public boolean isChannelVisible(int channel) {
- if (showOtherChannels_) {
- return true;
- } else {
- return channel == currentChannel_;
- }
- }
-
- /**
- * Returns true iff channels that aren't the current one are visible in the score.
- */
- public boolean getOtherChannelsVisible() {
- return showOtherChannels_;
- }
-
- /**
- * Sets whether channels that aren't the current one are visible in the score.
- */
- public void setOtherChannelsVisible(boolean visible) {
- showOtherChannels_ = visible;
- }
-
- /**
- * Returns the currently selected tool for this ScoreView.
- */
- public ScoreViewTool getTool() {
- return currentTool_;
- }
-
- /**
- * Sets a tool to be the current tool for this ScoreView. Informs listeners of the change.
- */
- public void setTool(ScoreViewTool tool) {
- ScoreViewTool previousTool = currentTool_;
- currentTool_ = tool;
- tool.onSelect(this, previousTool);
- if (listener_ != null) {
- listener_.onSetTool(tool);
- }
- invalidate();
- }
-
- /**
- * Returns the "snap to" setting for this ScoreView. @see setSnapTo().
- * @return the note that should be snapped to. For example, if editing should snap to the nearest
- * quarter note, then returns 0.25. For a whole note, 1.0. For no snapping, returns 0.0.
- */
- public double getSnapTo() {
- return snapTo_;
- }
-
- /**
- * Sets the "snap to" setting for this ScoreView. @see getSnapTo().
- * @param snapTo - the note that should be snapped to. For example, if editing should snap to the
- * nearest quarter note, then 0.25. For a whole note, 1.0. For no snapping, 0.0.
- */
- public void setSnapTo(double snapTo) {
- snapTo_ = snapTo;
- }
-
- /**
- * Returns the zoom setting for this control on the x-axis. @see setTimeZoom().
- * @return the multiplier for the x-axis on the viewport. 1.0 means the entire time of the score
- * is visible. 0.5 means only half of the score (time-wise) is visible. 2.0 means that the
- * entire score is shown, but only takes up half the screen. Any excess space is just "margin".
- */
- public double getTimeZoom() {
- return timeZoom_;
- }
-
- /**
- * Sets the zoom level for this control on the x-axis. @see getTimeZoom().
- * @param zoom - the multiplier for the x-axis on the viewport. 1.0 means the entire time of the
- * score is visible. 0.5 means only half of the score (time-wise) is visible. 2.0 means that the
- * entire score is shown, but only takes up half the screen. Any excess space is just "margin".
- */
- public void setTimeZoom(double zoom) {
- timeZoom_ = zoom;
- }
-
- /**
- * Returns the zoom setting for this control on the y-axis. @see setNoteZoom().
- * @return the multiplier for the y-axis on the viewport, which controls how many note keys are
- * visible. 1.0 means show the entire 88 keys of the piano are visible. N/88 means exactly N
- * keys are visible. Values larger than 1.0 means extra "margin" is shown at the top and bottom.
- */
- public double getNoteZoom() {
- return noteZoom_;
- }
-
- /**
- * Sets the zoom setting for this control on the y-axis. @see getNoteZoom().
- * @param zoom - the multiplier for the y-axis on the viewport, which controls how many note keys
- * are visible. 1.0 means show the entire 88 keys of the piano are visible. N/88 means exactly N
- * keys are visible. Values larger than 1.0 means extra "margin" is shown at the top and bottom.
- */
- public void setNoteZoom(double zoom) {
- noteZoom_ = zoom;
- }
-
- /**
- * Returns the left-most time currently visible in this control. @see setTimeOffset().
- * @return the time, in measures, from the beginning of the score to the first visible time
- * in the ScoreView. For example, 5.25 in 4/4 time would mean one quarter note past the end of
- * the 5th measure. Negative values mean margin is shown on the left side.
- */
- public double getTimeOffset() {
- return timeOffset_;
- }
-
- /**
- * Sets the left-most time currently visible in this control. @see getTimeOffset().
- * @param offset - The time, in measures, from the beginning of the score to the first visible
- * time in the ScoreView. For example, 5.25 in 4/4 time would mean one quarter note past the end
- * of the 5th measure. Negative values mean margin is shown on the left side.
- */
- public void setTimeOffset(double offset) {
- timeOffset_ = offset;
- }
-
- /**
- * Returns the bottom-most note key currently visible in this control. @see setNoteOffset().
- * @return the note number of the bottom key visible on the screen. 0.0 means the lowest note is
- * fully visible, with its bottom along the bottom edge of the screen. 1.0 means the lowest note
- * is not visible, but its top edge is along the bottom of the screen. 88.0 means no keys are
- * visible, but the top edge of the highest key is along the bottom of the screen.
- */
- public double getNoteOffset() {
- return noteOffset_;
- }
-
- /**
- * Sets the bottom-most note key currently visible in this control. @see getNoteOffset().
- * @param offset - the note number of the bottom key visible on the screen. 0.0 means the lowest
- * note is fully visible, with its bottom along the bottom edge of the screen. 1.0 means the
- * lowest note is not visible, but its top edge is along the bottom of the screen. 88.0 means no
- * keys are visible, but the top edge of the highest key is along the bottom of the screen.
- */
- public void setNoteOffset(double offset) {
- noteOffset_ = offset;
- }
-
- /**
- * Returns the max time viewable or editable by this ScoreView. @see setMaxTime().
- * @return the time, where 0.0 means no time, 1.0 means one measure, and 10 means ten measures.
- */
- public double getMaxTime() {
- return maxTime_;
- }
-
- /**
- * Sets the max time viewable or editable by this ScoreView. @see getMaxTime().
- * @param max - the time, where 0.0 means no time, 1.0 means one measure, and 10 for ten measures.
- */
- public void setMaxTime(double max) {
- maxTime_ = max;
- }
-
- /**
- * Returns the max possible note viewable or editable by this ScoreView. @see setMaxNote().
- * @return the note number. For a normal piano layout, this method should always return 88.0.
- */
- public double getMaxNote() {
- return maxNote_;
- }
-
- /**
- * Sets the max possible note viewable or editable by this ScoreView. @see getMaxNote().
- * @param max - the note number. For a normal piano layout, this should always be 88.0.
- */
- public void setMaxNote(double max) {
- maxNote_ = max;
- }
-
- /**
- * Returns the rectangle, in screen coordinates, where this ScoreView was most recently drawn.
- * @return a reference to the Rect.
- */
- public Rect getDrawingRect() {
- return drawingRect_;
- }
-
- /**
- * Returns the time (logical x) that corresponds to the given pixel (physical x).
- * @param pixelX - the x in screen coordinates.
- * @return the x in logical coordinates (the time, in measures, from the score start).
- */
- public double getTimeAt(int pixelX) {
- return timeOffset_ + ((double)(pixelX - drawingRect_.left) / drawingRect_.width()) / timeZoom_;
- }
-
- /**
- * Returns the pixel (physical x) that corresponds to the given time (logical x).
- * @param time - the time, in measures, from the score start.
- * @return the x offset of the given time, in screen coordinates.
- */
- public int getTimeX(double time) {
- return (int)(((time - timeOffset_) * timeZoom_) * drawingRect_.width() +
- drawingRect_.left + 0.5);
- }
-
- /**
- * Returns the note (logical y) that corresponds to the given pixel (physical y).
- * @param pixelY - the y in screen coordinates.
- * @return the y in logical coordinates (the note key, typically from 0 to 88.0).
- */
- public double getNoteAt(int pixelY) {
- return ((double)(drawingRect_.bottom - pixelY) / drawingRect_.height()) / noteZoom_ + noteOffset_;
- }
-
- /**
- * Returns the pixel (physical y) that corresponds to the given note (logical y).
- * @param note - the note key.
- * @return the y offset of the given note, in screen coordinates.
- */
- public int getNoteY(double note) {
- return (int)(drawingRect_.bottom - (note - noteOffset_) * drawingRect_.height() * noteZoom_);
- }
-
- /**
- * Returns the top-most event at the given coordinates.
- * @param physicalX - the x in screen coordinates.
- * @param physicalY - the y in screen coordinates.
- * @return the mutable event.
- */
- public Event.Builder getEventAt(int physicalX, int physicalY) {
- double time = getTimeAt(physicalX);
- double note = getNoteAt(physicalY);
- for (int i = score_.getEventCount() - 1; i >= 0; --i) {
- double eventStartTime = score_.getEvent(i).getStart();
- double eventEndTime = score_.getEvent(i).getEnd();
- double eventMinNote = score_.getEvent(i).getKey();
- double eventMaxNote = score_.getEvent(i).getKey() + 1;
- if (time >= eventStartTime &&
- time < eventEndTime &&
- note >= eventMinNote &&
- note < eventMaxNote) {
- return score_.getEventBuilder(i);
- }
- }
- return null;
- }
-
- /**
- * Sets the cursor position that shows where playback is in the score.
- * This should only be called from the Android UI thread.
- */
- public void setCursor(double cursor) {
- cursor_ = cursor;
- invalidate();
- }
-
- /**
- * Returns the color to use for representing the given channel in this ScoreView.
- * @param channel - the channel.
- * @return the color to use, Android style.
- */
- public int getColorForChannel(int channel) {
- switch (channel % CHANNELS) {
- case 0: return Color.rgb(0, 255, 255);
- case 1: return Color.rgb(255, 0, 255);
- case 2: return Color.rgb(255, 255, 0);
- case 3: return Color.rgb(255, 0, 0);
- case 4: return Color.rgb(0, 255, 0);
- case 5: return Color.rgb(0, 0, 255);
- }
- return Color.BLACK;
- }
-
- /**
- * Returns the icon to use for representing the given channel in this ScoreView.
- * @param channel - the channel.
- * @return the icon to use, as a Drawable.
- */
- public Drawable getIconForChannel(int channel) {
- return iconForChannel_[channel % iconForChannel_.length];
- }
-
- /**
- * Called to draw the ScoreView widget.
- * @param canvas - the canvas to draw the widget on.
- */
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- getDrawingRect(drawingRect_);
-
- // Clear the rectangle.
- fillPaint_.setColor(Color.WHITE);
- canvas.drawRect(drawingRect_, fillPaint_);
- strokePaint_.setStrokeWidth(1.0f);
-
- // Draw piano keys to mark the frequencies.
- for (int note = (int)minNote_; note < (int)maxNote_; ++note) {
- // Draw a single key that fills up a row.
- keyRect_.bottom = getNoteY(note);
- keyRect_.top = getNoteY(note + 1);
- keyRect_.left = getTimeX(0.0);
- keyRect_.right = getTimeX(maxTime_);
- strokePaint_.setStrokeWidth(2.0f);
- strokePaint_.setColor(Color.LTGRAY);
- if (Note.isNatural(note)) {
- fillPaint_.setColor(Color.WHITE);
- } else {
- fillPaint_.setColor(Color.LTGRAY);
- }
- canvas.drawRect(keyRect_, fillPaint_);
- canvas.drawRect(keyRect_, strokePaint_);
-
- if (currentTool_ != null) {
- currentTool_.afterDrawKey(note, canvas, keyRect_);
- }
- }
-
- // Draw lines to mark the measures.
- for (double i = minTime_ + 1; i < maxTime_; ++i) {
- strokePaint_.setColor(Color.LTGRAY);
- int x = getTimeX(i - 0.75);
- canvas.drawLine(x, drawingRect_.top, x, drawingRect_.bottom, strokePaint_);
-
- strokePaint_.setColor(Color.GRAY);
- x = getTimeX(i - 0.5);
- canvas.drawLine(x, drawingRect_.top, x, drawingRect_.bottom, strokePaint_);
-
- strokePaint_.setColor(Color.LTGRAY);
- x = getTimeX(i - 0.25);
- canvas.drawLine(x, drawingRect_.top, x, drawingRect_.bottom, strokePaint_);
-
- strokePaint_.setColor(Color.BLACK);
- x = getTimeX(i);
- canvas.drawLine(x, drawingRect_.top, x, drawingRect_.bottom, strokePaint_);
- }
-
- // Draw the margins.
- double leftMargin = getTimeX(minTime_);
- if (leftMargin > drawingRect_.left) {
- canvas.drawRect(drawingRect_.left,
- drawingRect_.top,
- (float)leftMargin,
- drawingRect_.bottom,
- marginPaint_);
- }
- double rightMargin = getTimeX(maxTime_);
- if (rightMargin < drawingRect_.right) {
- canvas.drawRect((float)rightMargin,
- drawingRect_.top,
- drawingRect_.right,
- drawingRect_.bottom,
- marginPaint_);
- }
- double topMargin = getNoteY(maxNote_);
- if (topMargin > drawingRect_.top) {
- canvas.drawRect(drawingRect_.left,
- drawingRect_.top,
- drawingRect_.right,
- (float)topMargin,
- marginPaint_);
- }
- double bottomMargin = getNoteY(minNote_);
- if (bottomMargin < drawingRect_.bottom) {
- canvas.drawRect(drawingRect_.left,
- (float)bottomMargin,
- drawingRect_.right,
- drawingRect_.bottom,
- marginPaint_);
- }
-
- // Draw the sequence.
- for (int i = 0; i < score_.getEventCount(); ++i) {
- Event event = score_.getEvent(i);
- eventRect_.left = getTimeX(event.getStart());
- eventRect_.top = getNoteY(event.getKey() + 1);
- eventRect_.right = getTimeX(event.getEnd());
- eventRect_.bottom = getNoteY(event.getKey());
-
- if (!event.hasKeyEvent() || isChannelVisible(event.getKeyEvent().getChannel())) {
- if (event.getSelected()) {
- if (event.hasKeyEvent()) {
- fillPaint_.setColor(getColorForChannel(event.getKeyEvent().getChannel()));
- strokePaint_.setColor(Color.BLACK);
- } else {
- fillPaint_.setColor(Color.BLACK);
- strokePaint_.setColor(Color.WHITE);
- }
- fillPaint_.setAlpha(255);
- strokePaint_.setStrokeWidth(5.0f);
- } else {
- if (event.hasKeyEvent()) {
- fillPaint_.setColor(getColorForChannel(event.getKeyEvent().getChannel()));
- strokePaint_.setColor(Color.BLACK);
- } else {
- fillPaint_.setColor(Color.BLACK);
- strokePaint_.setColor(Color.WHITE);
- }
- fillPaint_.setAlpha(127);
- strokePaint_.setStrokeWidth(1.0f);
- }
- canvas.drawRect(eventRect_, fillPaint_);
- canvas.drawRect(eventRect_, strokePaint_);
-
- if (currentTool_ != null) {
- currentTool_.afterDrawEvent(event, canvas, eventRect_);
- }
- }
- }
-
- // Draw the cursor.
- strokePaint_.setColor(Color.rgb(0, 175, 0));
- strokePaint_.setStrokeWidth(8.0f);
- canvas.drawLine(getTimeX(cursor_), drawingRect_.top,
- getTimeX(cursor_), drawingRect_.bottom, strokePaint_);
-
- // Draw the scroll arrows, if visible.
- if (arrowsVisible_) {
- upIcon_.setBounds(getDrawingRect().left + 50,
- getDrawingRect().top + 50,
- getDrawingRect().left + 50 + upIcon_.getIntrinsicWidth(),
- getDrawingRect().top + 50 + downIcon_.getIntrinsicHeight());
- downIcon_.setBounds(getDrawingRect().left + 50,
- (getDrawingRect().bottom - 50) - downIcon_.getIntrinsicHeight(),
- getDrawingRect().left + 50 + upIcon_.getIntrinsicWidth(),
- getDrawingRect().bottom - 50);
-
- if (upSelected_) {
- fillPaint_.setColor(Color.WHITE);
- } else {
- fillPaint_.setColor(Color.BLACK);
- }
- canvas.drawCircle(upIcon_.getBounds().centerX(),
- upIcon_.getBounds().centerY(),
- upIcon_.getBounds().width(),
- fillPaint_);
- upIcon_.draw(canvas);
-
- if (downSelected_) {
- fillPaint_.setColor(Color.WHITE);
- } else {
- fillPaint_.setColor(Color.BLACK);
- }
- canvas.drawCircle(downIcon_.getBounds().centerX(),
- downIcon_.getBounds().centerY(),
- downIcon_.getBounds().width(),
- fillPaint_);
- downIcon_.draw(canvas);
-
- // Make the bounds for the icons a little larger so they're easier to hit.
- downIcon_.getBounds().inset(-50, -50);
- upIcon_.getBounds().inset(-50, -50);
- }
-
- if (currentTool_ != null) {
- currentTool_.afterDrawScore(this, canvas, drawingRect_);
- }
- }
-
- /**
- * Handler for all touch events.
- */
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- // Check if they touched the arrows.
- int action = event.getAction();
- int actionCode = action & MotionEvent.ACTION_MASK;
- if (actionCode == MotionEvent.ACTION_DOWN) {
- if (upIcon_.getBounds().contains((int)event.getX(), (int)event.getY())) {
- upSelected_ = true;
- invalidate();
- return true;
- } else if (downIcon_.getBounds().contains((int)event.getX(), (int)event.getY())) {
- downSelected_ = true;
- invalidate();
- return true;
- } else {
- arrowsVisible_ = false;
- invalidate();
- }
- } else if (actionCode == MotionEvent.ACTION_UP) {
- arrowsVisible_ = true;
- if (upSelected_) {
- // Scroll up.
- if (getNoteOffset() < maxNote_) {
- setNoteOffset(getNoteOffset() + 1);
- }
- upSelected_ = false;
- }
- if (downSelected_) {
- // Scroll down.
- if (getNoteOffset() > minNote_) {
- setNoteOffset(getNoteOffset() - 1);
- }
- downSelected_ = false;
- }
- invalidate();
- }
-
- // Delegate the touch to the current tool.
- if (!upSelected_ && !downSelected_ && currentTool_ != null) {
- return currentTool_.onTouch(this, event);
- } else {
- return false;
- }
- }
-
- /**
- * Layout measurement for this widget.
- * This method just sets a basic minimum size and makes the widget maximized otherwise.
- */
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-
- int width = 0;
- int height = 0;
-
- switch (widthMode) {
- case MeasureSpec.EXACTLY:
- width = widthSize;
- break;
- case MeasureSpec.AT_MOST:
- width = widthSize;
- break;
- case MeasureSpec.UNSPECIFIED:
- width = 10;
- break;
- }
-
- switch (heightMode) {
- case MeasureSpec.EXACTLY:
- height = heightSize;
- break;
- case MeasureSpec.AT_MOST:
- height = heightSize;
- break;
- case MeasureSpec.UNSPECIFIED:
- height = 10;
- break;
- }
-
- setMeasuredDimension(width, height);
- }
-
- /**
- * Connects the ScoreView to a Synthesizer for playback.
- * @synth - The synthesizer to connect to.
- */
- public void bindTo(final MidiListener synth) {
- synthesizer_ = synth;
- }
-
- /**
- * Returns the synthesizer connected to this ScoreView.
- * @return the connected synthesizer.
- */
- public MidiListener getSynthesizer() {
- return synthesizer_;
- }
-
- /**
- * Sets the listener to notify of events in this control.
- * @param listener - the listener to notify.
- */
- public void setListener(ScoreViewListener listener) {
- listener_ = listener;
- }
-
- // The score being edited, played, etc by this control.
- private Score.Builder score_;
-
- // The current tool being used.
- private ScoreViewTool currentTool_;
-
- // The currently selected channel (instrument).
- private int currentChannel_;
-
- // Whether to show channels other than the currently selected one.
- private boolean showOtherChannels_;
-
- // The set of icons to use for each channel.
- private Drawable[] iconForChannel_;
-
- // What granularity of note to snap to when editing. See getSnapTo and setSnapTo().
- private double snapTo_;
-
- // The min, max and current viewport for the x and y axes.
- private double timeZoom_;
- private double timeOffset_;
- private double minTime_;
- private double maxTime_;
- private double noteZoom_;
- private double noteOffset_;
- private double minNote_;
- private double maxNote_;
-
- // A cursor that indicates where playback is in the score, in logical coordinates.
- private double cursor_;
-
- // The synthesizer this control is bound to.
- private MidiListener synthesizer_;
-
- // The listener to notify of events in this control.
- private ScoreViewListener listener_;
-
- // Buttons to let the user move up and down without switching to the viewport tool.
- private boolean arrowsVisible_;
- private boolean upSelected_;
- private boolean downSelected_;
- private Drawable upIcon_;
- private Drawable downIcon_;
-
- // These are basically stack variables for onDraw. They're member variables only so that we can
- // avoid reallocating them every time the keyboard is redrawn.
- //
- // The most recent screen rect that this keyboard was drawn into.
- private Rect drawingRect_;
- private Rect keyRect_;
- private Rect eventRect_;
- private Paint fillPaint_;
- private Paint strokePaint_;
- private Paint marginPaint_;
-
- // The number of channels (instruments) edittable by this control.
- private static final int CHANNELS = 5;
-
- @SuppressWarnings("unused")
- private Logger logger_;
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/score/ScoreViewListener.java b/android/src/com/levien/synthesizer/android/widgets/score/ScoreViewListener.java
deleted file mode 100644
index 2dd5349..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/score/ScoreViewListener.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.score;
-
-/**
- * A listener for events happening in a ScoreView.
- */
-public interface ScoreViewListener {
- /**
- * Called when a new tool is selected for the ScoreView.
- */
- void onSetTool(ScoreViewTool tool);
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/score/ScoreViewTool.java b/android/src/com/levien/synthesizer/android/widgets/score/ScoreViewTool.java
deleted file mode 100644
index 5f5efb0..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/score/ScoreViewTool.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.score;
-
-import com.levien.synthesizer.core.music.Music.Event;
-
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.view.MotionEvent;
-
-/**
- * A base class for tools on the ScoreView's toolbar.
- */
-public abstract class ScoreViewTool {
- /**
- * Draws the button on the toolbar.
- * @param canvas - The canvas to draw the button on.
- * @param score - The ScoreView that this tool is for.
- * @param rect - The area of the button to be drawn, including any margin.
- * @param margin - The preferred margin around the button, in screen coordinates.
- */
- public abstract void drawButton(Canvas canvas, ScoreView score, Rect rect, float margin);
-
- /**
- * Called when this tool is selected.
- * @param view - The ScoreView that this tool is for.
- * @param previousTool - The tool that was selected when this one was chosen.
- */
- public void onSelect(ScoreView view, ScoreViewTool previousTool) {}
-
- /**
- * Called when the user touches the ScoreView while this tool is selected.
- * @param view - The ScoreView that this tool is for.
- * @param event - The touch event that triggered this handler.
- * @return true iff this tool handled the touch event.
- */
- public boolean onTouch(ScoreView view, MotionEvent event) {
- return false;
- }
-
- /**
- * Called after each key is drawn, to give this tool a chance to draw over it.
- * See ScoreView.onDraw() for more information on how ScoreView is drawn.
- * @param key - The key that was drawn.
- * @param canvas - The canvas the key is drawn into.
- * @param rect - The area of the key on the canvas.
- */
- public void afterDrawKey(int key, Canvas canvas, Rect rect) {}
-
- /**
- * Called after each event is drawn, to give this tool a chance to draw over it.
- * See ScoreView.onDraw() for more information on how ScoreView is drawn.
- * @param event - The event that was drawn.
- * @param canvas - The canvas the key is drawn into.
- * @param rect - The area of the key on the canvas.
- */
- public void afterDrawEvent(Event event, Canvas canvas, Rect rect) {}
-
- /**
- * Called after the entire score is drawn, to give this tool a chance to draw over it.
- * See ScoreView.onDraw() for more information on how ScoreView is drawn.
- * @param view - The ScoreView being drawn.
- * @param canvas - The canvas the key is drawn into.
- * @param rect - The area of the key on the canvas.
- */
- public void afterDrawScore(ScoreView view, Canvas canvas, Rect rect) {}
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/score/ScoreViewToolbar.java b/android/src/com/levien/synthesizer/android/widgets/score/ScoreViewToolbar.java
deleted file mode 100644
index 2d97e51..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/score/ScoreViewToolbar.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.score;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-
-/**
- * A toolbar that goes in a ScoreView and lets the user choose which tool to use on it.
- */
-public class ScoreViewToolbar extends View implements ScoreViewListener {
- /** Basic constructor for an Android widget. */
- public ScoreViewToolbar(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- paint_ = new Paint();
- rect_ = new Rect();
- textRect_ = new Rect();
-
- // Just hard-code the list of tools.
- tool_ = new ScoreViewTool[13];
- tool_[0] = new PlayButton(this, context);
- tool_[1] = new ViewportTool(context);
- tool_[2] = new EditEventTool(context);
- tool_[3] = new NewEventTool(context, (EditEventTool)tool_[2]);
- tool_[4] = new NewLoopTool(context, (EditEventTool)tool_[2]);
- tool_[5] = new HideChannelButton(context);
- tool_[6] = new PlayTool(context);
- tool_[7] = new SelectChannelButton(context, 0);
- tool_[8] = new SelectChannelButton(context, 1);
- tool_[9] = new SelectChannelButton(context, 2);
- tool_[10] = new SelectChannelButton(context, 3);
- tool_[11] = new SelectChannelButton(context, 4);
- tool_[12] = new SnapTool(context);
-
- toolRect_ = new Rect[tool_.length];
- for (int i = 0; i < tool_.length; ++i) {
- toolRect_[i] = new Rect();
- }
- }
-
- /**
- * Sets the ScoreView that this toolbar controls.
- * @param score - the ScoreView.
- */
- public void setScoreView(ScoreView score) {
- score_ = score;
- score_.setListener(this);
- score_.setTool(tool_[1]);
- invalidate();
- }
-
- /**
- * Sets the current tool.
- * @param tool - the tool to use.
- */
- public void onSetTool(ScoreViewTool tool) {
- invalidate();
- }
-
- /**
- * Touch event handler.
- */
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- int action = event.getAction();
- switch (action) {
- case MotionEvent.ACTION_DOWN: {
- getDrawingRect(rect_);
- for (int i = 0; i < tool_.length; ++i) {
- if (toolRect_[i].contains((int)event.getX(), (int)event.getY())) {
- score_.setTool(tool_[i]);
- invalidate();
- break;
- }
- }
- break;
- }
-
- case MotionEvent.ACTION_MOVE: {
- break;
- }
-
- case MotionEvent.ACTION_UP: {
- break;
- }
- }
- return true;
- }
-
- /**
- * Drawing handler.
- */
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- getDrawingRect(rect_);
- //rect_.set(rect_);
-
- paint_.setColor(Color.BLACK);
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect_, paint_);
-
- // Draw the buttons.
- float margin = 15.0f;
- float waveHeight = (rect_.height() - 2.0f * margin);
- float waveWidth = waveHeight;
-
- float xOffset = margin;
- float yOffset = margin;
- for (int i = 0; i < tool_.length; ++i) {
- paint_.setTextSize(24.0f);
- paint_.setColor(Color.WHITE);
- if (i == 1) {
- xOffset += 2 * margin;
- paint_.getTextBounds("Tools ", 0, 6, textRect_);
- canvas.drawText("Tools ", xOffset, yOffset + (waveHeight + textRect_.height()) / 2, paint_);
- xOffset += textRect_.width();
- xOffset += margin;
- } else if (i == 7) {
- xOffset += 2 * margin;
- paint_.getTextBounds("Instruments ", 0, 12, textRect_);
- canvas.drawText("Instruments ", xOffset, yOffset + (waveHeight + textRect_.height()) / 2, paint_);
- xOffset += textRect_.width();
- xOffset += margin;
- } else if (i == 12) {
- xOffset += 2 * margin;
- paint_.getTextBounds("Snap to ", 0, 8, textRect_);
- canvas.drawText("Snap to ", xOffset, yOffset + (waveHeight + textRect_.height()) / 2, paint_);
- xOffset += textRect_.width();
- xOffset += margin;
- }
- paint_.setColor(Color.BLACK);
-
- toolRect_[i].left = (int)xOffset;
- toolRect_[i].top = (int)yOffset;
- toolRect_[i].right = (int)(xOffset + waveWidth);
- toolRect_[i].bottom = (int)(yOffset + waveHeight);
-
- tool_[i].drawButton(canvas, score_, toolRect_[i], margin);
-
- xOffset += waveWidth;
- xOffset += margin;
- }
- }
-
- /**
- * Layout measurement for this widget.
- * This method just sets a basic minimum size and makes the width maximized otherwise.
- */
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-
- int width = 0;
- int height = 0;
-
- switch (widthMode) {
- case MeasureSpec.EXACTLY:
- width = widthSize;
- break;
- case MeasureSpec.AT_MOST:
- width = widthSize;
- break;
- case MeasureSpec.UNSPECIFIED:
- width = 10;
- break;
- }
-
- switch (heightMode) {
- case MeasureSpec.EXACTLY:
- height = heightSize;
- break;
- case MeasureSpec.AT_MOST:
- height = 150;
- break;
- case MeasureSpec.UNSPECIFIED:
- height = 10;
- break;
- }
-
- setMeasuredDimension(width, height);
- }
-
- // The score being edited.
- private ScoreView score_;
-
- // Structures used in drawing that we don't want to reallocate every time we draw.
- private Paint paint_;
- private Rect rect_;
- private Rect textRect_;
-
- // The set of available tools.
- private ScoreViewTool[] tool_;
-
- // The rect that each tool occupied the last time it was drawn.
- private Rect[] toolRect_;
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/score/SelectChannelButton.java b/android/src/com/levien/synthesizer/android/widgets/score/SelectChannelButton.java
deleted file mode 100644
index 4e653f2..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/score/SelectChannelButton.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.score;
-
-import java.util.logging.Logger;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-
-/**
- * A tool for selecting a particular channel in a ScoreView.
- */
-public class SelectChannelButton extends ScoreViewTool {
- /**
- * Creates a tool for selecting the given channel, loading resources using the given context.
- */
- SelectChannelButton(Context context, int channel) {
- logger_ = Logger.getLogger(getClass().getName());
- channel_ = channel;
- paint_ = new Paint();
- }
-
- /**
- * Returns the channel that this control selects.
- */
- public int getChannel() {
- return channel_;
- }
-
- /**
- * Draws the button on the toolbar.
- * @param canvas - The canvas to draw the button on.
- * @param score - The ScoreView that this toolbar is for.
- * @param rect - The area of the button to be drawn, including any margin.
- * @param margin - The preferred margin around the button, in screen coordinates.
- */
- @Override
- public void drawButton(Canvas canvas, ScoreView score, Rect rect, float margin) {
- if (score.getTool() == this) {
- paint_.setColor(Color.WHITE);
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect.left - margin / 2,
- rect.top - margin / 2,
- rect.right + margin / 2,
- rect.bottom + margin / 2,
- paint_);
- }
-
- if (getChannel() == score.getCurrentChannel()) {
- paint_.setColor(score.getColorForChannel(getChannel()));
- } else {
- paint_.setColor(Color.BLACK);
- }
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect, paint_);
- Drawable icon = score.getIconForChannel(getChannel());
- icon.setBounds(rect);
- icon.draw(canvas);
- }
-
- /**
- * Called when this tool is selected.
- * Changes the selected channel for the view and then reselects the previously selected tool.
- * @param view - The ScoreView that this toolbar is for.
- * @param previousTool - The tool that was selected when this one was chosen.
- */
- @Override
- public void onSelect(ScoreView view, ScoreViewTool previousTool) {
- view.setCurrentChannel(channel_);
- view.setTool(previousTool);
- }
-
- // The channel this control selects.
- private int channel_;
-
- // Some objects used in drawing. They are owned here so that they don't have to be reallocated
- // and garbage collected for every pass of drawing.
- private Paint paint_;
-
- @SuppressWarnings("unused")
- private Logger logger_;
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/score/SnapTool.java b/android/src/com/levien/synthesizer/android/widgets/score/SnapTool.java
deleted file mode 100644
index 3805df6..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/score/SnapTool.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.score;
-
-import com.levien.synthesizer.R;
-
-import java.util.logging.Logger;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-
-/**
- * A control for selecting the "snap to" setting of a ScoreView.
- * @see ScoreView
- */
-public class SnapTool extends ScoreViewTool {
- /**
- * Creates a new SnapTool, loading resources from the given context.
- */
- SnapTool(Context context) {
- logger_ = Logger.getLogger(getClass().getName());
-
- customIcon_ = context.getResources().getDrawable(R.drawable.unknown_note);
- noneIcon_ = context.getResources().getDrawable(R.drawable.no_note);
- thirtySecondIcon_ = context.getResources().getDrawable(R.drawable.thirtysecond_note);
- sixteenthIcon_ = context.getResources().getDrawable(R.drawable.sixteenth_note);
- eighthIcon_ = context.getResources().getDrawable(R.drawable.eighth_note);
- quarterIcon_ = context.getResources().getDrawable(R.drawable.quarter_note);
- halfIcon_ = context.getResources().getDrawable(R.drawable.half_note);
- wholeIcon_ = context.getResources().getDrawable(R.drawable.whole_note);
-
- paint_ = new Paint();
- }
-
- /**
- * Called when this tool is selected. Changes the "snap to" setting for the score view and then
- * reselects the previously selected tool.
- * @param view - The ScoreView that this toolbar is for.
- * @param previousTool - The tool that was selected when this one was chosen.
- */
- @Override
- public void onSelect(ScoreView view, ScoreViewTool previousTool) {
- if (view.getSnapTo() == 0.0) {
- view.setSnapTo(1.0);
- } else if (view.getSnapTo() <= 0.03125) {
- view.setSnapTo(0.0);
- } else {
- view.setSnapTo(view.getSnapTo() / 2.0);
- }
- view.setTool(previousTool);
- }
-
- /**
- * Draws the button on the toolbar.
- * @param canvas - The canvas to draw the button on.
- * @param score - The ScoreView that this toolbar is for.
- * @param rect - The area of the button to be drawn, including any margin.
- * @param margin - The preferred margin around the button, in screen coordinates.
- */
- @Override
- public void drawButton(Canvas canvas, ScoreView score, Rect rect, float margin) {
- if (score.getTool() == this) {
- paint_.setColor(Color.WHITE);
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect.left - margin / 2,
- rect.top - margin / 2,
- rect.right + margin / 2,
- rect.bottom + margin / 2,
- paint_);
- }
-
- paint_.setColor(Color.BLACK);
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect, paint_);
- if (score.getSnapTo() == 1.0) {
- wholeIcon_.setBounds(rect);
- wholeIcon_.draw(canvas);
- } else if (score.getSnapTo() == 0.5) {
- halfIcon_.setBounds(rect);
- halfIcon_.draw(canvas);
- } else if (score.getSnapTo() == 0.25) {
- quarterIcon_.setBounds(rect);
- quarterIcon_.draw(canvas);
- } else if (score.getSnapTo() == 0.125) {
- eighthIcon_.setBounds(rect);
- eighthIcon_.draw(canvas);
- } else if (score.getSnapTo() == 0.0625) {
- sixteenthIcon_.setBounds(rect);
- sixteenthIcon_.draw(canvas);
- } else if (score.getSnapTo() == 0.03125) {
- thirtySecondIcon_.setBounds(rect);
- thirtySecondIcon_.draw(canvas);
- } else if (score.getSnapTo() == 0.0) {
- noneIcon_.setBounds(rect);
- noneIcon_.draw(canvas);
- } else {
- customIcon_.setBounds(rect);
- customIcon_.draw(canvas);
- }
- }
-
- // Some objects used in drawing. They are owned here so that they don't have to be reallocated
- // and garbage collected for every pass of drawing.
- private Paint paint_;
- private Drawable customIcon_;
- private Drawable noneIcon_;
- private Drawable thirtySecondIcon_;
- private Drawable sixteenthIcon_;
- private Drawable eighthIcon_;
- private Drawable quarterIcon_;
- private Drawable halfIcon_;
- private Drawable wholeIcon_;
-
- @SuppressWarnings("unused")
- private Logger logger_;
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/score/ViewportTool.java b/android/src/com/levien/synthesizer/android/widgets/score/ViewportTool.java
deleted file mode 100644
index 19b16f4..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/score/ViewportTool.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.score;
-
-import java.util.logging.Logger;
-
-import com.levien.synthesizer.R;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.view.MotionEvent;
-
-/**
- * A tool for adjusting the visible logical area of a ScoreView.
- * When this tool is selected, touching moves around the viewport, and pinching zooms in/out.
- */
-public class ViewportTool extends ScoreViewTool {
- /**
- * Creates a new ViewportTool, loading resources from the given context.
- */
- ViewportTool(Context context) {
- logger_ = Logger.getLogger(getClass().getName());
-
- startX1_ = 0;
- startX2_ = 0;
- startY1_ = 0;
- startY2_ = 0;
-
- icon_ = context.getResources().getDrawable(R.drawable.zoom);
- paint_ = new Paint();
- }
-
- /**
- * Draws the button on the toolbar.
- * @param canvas - The canvas to draw the button on.
- * @param score - The ScoreView that this toolbar is for.
- * @param rect - The area of the button to be drawn, including any margin.
- * @param margin - The preferred margin around the button, in screen coordinates.
- */
- @Override
- public void drawButton(Canvas canvas, ScoreView score, Rect rect, float margin) {
- if (score.getTool() == this) {
- paint_.setColor(Color.WHITE);
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect.left - margin / 2,
- rect.top - margin / 2,
- rect.right + margin / 2,
- rect.bottom + margin / 2,
- paint_);
- }
-
- paint_.setColor(Color.BLACK);
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect, paint_);
- icon_.setBounds(rect);
- icon_.draw(canvas);
- }
-
- /**
- * Called when the user touches the ScoreView while this tool is selected.
- * @param view - The ScoreView that this tool is for.
- * @param event - The touch event that triggered this handler.
- * @return true iff this tool handled the touch event.
- */
- @Override
- public boolean onTouch(ScoreView view, MotionEvent event) {
- int action = event.getAction();
- int actionCode = action & MotionEvent.ACTION_MASK;
- boolean redraw = false;
- double timeZoom = view.getTimeZoom();
- double timeOffset = view.getTimeOffset();
- double noteZoom = view.getNoteZoom();
- double noteOffset = view.getNoteOffset();
-
- if (actionCode == MotionEvent.ACTION_DOWN) {
- int pointerId = event.getPointerId(0);
- startX1_ = (int)event.getX();
- startY1_ = (int)event.getY();
- if (pointerId != 0) {
- logger_.severe("Initial pointer has id " + pointerId);
- }
- } else if (actionCode == MotionEvent.ACTION_POINTER_DOWN) {
- int pointerId = action >> MotionEvent.ACTION_POINTER_ID_SHIFT;
- int pointerIndex = event.findPointerIndex(pointerId);
- if (pointerId == 1 && pointerIndex >= 0) {
- startX2_ = (int)event.getX(pointerIndex);
- startY2_ = (int)event.getY(pointerIndex);
- }
- } else if (actionCode == MotionEvent.ACTION_MOVE) {
- double currentX1 = 0;
- double currentX2 = 0;
- double currentY1 = 0;
- double currentY2 = 0;
- boolean has1 = false;
- boolean has2 = false;
-
- // Find the current positions of the fingers.
- for (int pointerIndex = 0; pointerIndex < event.getPointerCount(); ++pointerIndex) {
- int pointerId = event.getPointerId(pointerIndex);
- if (pointerId >= 0) {
- int x = (int)event.getX(pointerIndex);
- int y = (int)event.getY(pointerIndex);
- if (pointerId == 0) {
- currentX1 = x;
- currentY1 = y;
- has1 = true;
- } else if (pointerId == 1) {
- currentX2 = x;
- currentY2 = y;
- has2 = true;
- }
- }
- }
-
- if (has1 && has2) {
- // Enforce that finger 1 is to the left of and above finger 2.
- if (currentX2 < currentX1) {
- double temp = currentX1;
- currentX1 = currentX2;
- currentX2 = temp;
- }
- if (currentY2 < currentY1) {
- double temp = currentY1;
- currentY1 = currentY2;
- currentY2 = temp;
- }
- if (startX2_ < startX1_) {
- double temp = startX1_;
- startX1_ = startX2_;
- startX2_ = temp;
- }
- if (startY2_ < startY1_) {
- double temp = startY1_;
- startY1_ = startY2_;
- startY2_ = temp;
- }
-
- // Make sure the fingers aren't too close together.
- if (startX2_ - startX1_ < 50.0) {
- startX2_ = startX1_ + 50.0;
- }
- if (currentX2 - currentX1 < 50.0) {
- currentX2 = currentX1 + 50.0;
- }
- if (startY2_ - startY1_ < 50.0) {
- startY2_ = startY1_ + 50.0;
- }
- if (currentY2 - currentY1 < 50.0) {
- currentY2 = currentY1 + 50.0;
- }
-
- // Figure out the parameters of the new viewport.
- double scaleXFactor = Math.abs((currentX1 - currentX2) / (startX1_ - startX2_));
- timeOffset += (startX1_ - currentX1 / scaleXFactor) /
- (timeZoom * view.getDrawingRect().width());
- timeZoom *= scaleXFactor;
-
- double scaleYFactor = Math.abs((currentY1 - currentY2) / (startY1_ - startY2_));
- noteOffset -= (startY1_ - currentY1/scaleYFactor -
- view.getDrawingRect().bottom * (1 - 1/scaleYFactor)) /
- (noteZoom * view.getDrawingRect().height());
-
- noteZoom *= scaleYFactor;
-
- // Update the tracking.
- startX1_ = currentX1;
- startX2_ = currentX2;
- startY1_ = currentY1;
- startY2_ = currentY2;
- redraw = true;
- } else if (has1) {
- // Move the viewport.
- timeOffset += (startX1_ - currentX1) / (timeZoom * view.getDrawingRect().width());
- startX1_ = currentX1;
- noteOffset -= (startY1_ - currentY1) / (noteZoom * view.getDrawingRect().height());
- startY1_ = currentY1;
- redraw = true;
- }
- } else if (actionCode == MotionEvent.ACTION_UP) {
- // Snap back so we aren't showing much margin.
- // This code is commented out because it's actually much more intuitive if it doesn't snap
- // back but just shows some margin.
- /*
- if (scaleX < 1.0 / maxX) {
- offsetX = 0.0;
- scaleX = 1.0 / maxX;
- redraw = true;
- }
- if (scaleY < 1.0 / maxY) {
- offsetY = 0.0;
- scaleY = 1.0 / maxY;
- redraw = true;
- }
- if (offsetX < 0.0) {
- offsetX = 0.0;
- redraw = true;
- }
- if (offsetY < 0.0) {
- offsetY = 0.0;
- redraw = true;
- }
- if (offsetX > maxX - 1.0 / scaleX) {
- offsetX = maxX - 1.0 / scaleX;
- redraw = true;
- }
- if (offsetY > maxY - 1.0 / scaleY) {
- offsetY = maxY - 1.0 / scaleY;
- redraw = true;
- }
- */
- } else if (actionCode == MotionEvent.ACTION_POINTER_UP) {
- } else {
- return view.onTouchEvent(event);
- }
-
- view.setTimeZoom(timeZoom);
- view.setTimeOffset(timeOffset);
- view.setNoteZoom(noteZoom);
- view.setNoteOffset(noteOffset);
-
- if (redraw) {
- view.invalidate();
- }
-
- return true;
- }
-
- // The screen coordinates of the first and second fingers pressed on the ScoreView.
- // These are updated every time the viewport is updated.
- private double startX1_;
- private double startX2_;
- private double startY1_;
- private double startY2_;
-
- // Some objects used in drawing. They are owned here so that they don't have to be reallocated
- // and garbage collected for every pass of drawing.
- private Paint paint_;
- private Drawable icon_;
-
- private Logger logger_;
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/waveform/WaveformListener.java b/android/src/com/levien/synthesizer/android/widgets/waveform/WaveformListener.java
deleted file mode 100644
index d8b9ebb..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/waveform/WaveformListener.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.waveform;
-
-/**
- * WaveformListener is an interface for getting events when a WaveformView's value changes.
- */
-public interface WaveformListener {
- /**
- * Called when the value changes.
- */
- void onWaveformChanged(String waveform);
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/waveform/WaveformRowView.java b/android/src/com/levien/synthesizer/android/widgets/waveform/WaveformRowView.java
deleted file mode 100644
index cd3b5a0..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/waveform/WaveformRowView.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.waveform;
-
-import com.levien.synthesizer.core.model.WaveformInput;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-
-/**
- * WaveformRowView is like a WaveformView, but it arranges its buttons in a row.
- */
-public class WaveformRowView extends WaveformView {
- /** Basic constructor for an Android widget. */
- public WaveformRowView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- /**
- * Touch event handler.
- */
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- int action = event.getAction();
- switch (action) {
- case MotionEvent.ACTION_DOWN: {
- getDrawingRect(rect_);
- double x = (event.getX() - rect_.left) / rect_.width();
- if (x < 1.0/6.0f) {
- setWaveform(WaveformInput.SINE);
- } else if (x < 2.0/6.0f) {
- setWaveform(WaveformInput.TRIANGLE);
- } else if (x < 3.0/6.0f) {
- setWaveform(WaveformInput.SQUARE);
- } else if (x < 4.0/6.0f) {
- setWaveform(WaveformInput.SAWTOOTH);
- } else if (x < 5.0/6.0f) {
- setWaveform(WaveformInput.NOISE);
- } else {
- CharSequence[] items = new CharSequence[input_.getWaveformCount()];
- for (int i = 0; i < items.length; ++i) {
- items[i] = input_.getWaveform(i);
- }
- AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
- builder.setItems(items, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- setWaveform(input_.getWaveform(which));
- }
- });
- builder.create().show();
- }
- invalidate();
- break;
- }
-
- case MotionEvent.ACTION_MOVE: {
- break;
- }
-
- case MotionEvent.ACTION_UP: {
- break;
- }
- }
- return true;
- }
-
- /**
- * Drawing handler.
- */
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- getDrawingRect(rect_);
- rect_.set(rect_);
-
- paint_.setColor(Color.BLACK);
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect_, paint_);
-
- // Draw waveforms.
- float lineWidth = 5.0f;
- float margin = 15.0f;
- float waveWidth = (rect_.width() - 7.0f * margin) / 6.0f;
- float waveHeight = (rect_.height() - 2.0f * margin);
-
- float xOffset = margin;
- float yOffset = margin;
- drawSine(canvas, xOffset, yOffset, waveWidth, waveHeight, margin, lineWidth);
- xOffset += waveWidth;
- xOffset += margin;
- drawTriangle(canvas, xOffset, yOffset, waveWidth, waveHeight, margin, lineWidth);
- xOffset += waveWidth;
- xOffset += margin;
- drawSquare(canvas, xOffset, yOffset, waveWidth, waveHeight, margin, lineWidth);
- xOffset += waveWidth;
- xOffset += margin;
- drawSawtooth(canvas, xOffset, yOffset, waveWidth, waveHeight, margin, lineWidth);
- xOffset += waveWidth;
- xOffset += margin;
- drawNoise(canvas, xOffset, yOffset, waveWidth, waveHeight, margin, lineWidth);
- xOffset += waveWidth;
- xOffset += margin;
- drawOther(canvas, xOffset, yOffset, waveWidth, waveHeight, margin, lineWidth);
- }
-
- /**
- * Layout measurement for this widget.
- * This method just sets a basic minimum size and makes the width maximized otherwise.
- */
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-
- int width = 0;
- int height = 0;
-
- switch (widthMode) {
- case MeasureSpec.EXACTLY:
- width = widthSize;
- break;
- case MeasureSpec.AT_MOST:
- width = widthSize;
- break;
- case MeasureSpec.UNSPECIFIED:
- width = 10;
- break;
- }
-
- switch (heightMode) {
- case MeasureSpec.EXACTLY:
- height = heightSize;
- break;
- case MeasureSpec.AT_MOST:
- height = 150;
- break;
- case MeasureSpec.UNSPECIFIED:
- height = 10;
- break;
- }
-
- setMeasuredDimension(width, height);
- }
-}
diff --git a/android/src/com/levien/synthesizer/android/widgets/waveform/WaveformView.java b/android/src/com/levien/synthesizer/android/widgets/waveform/WaveformView.java
deleted file mode 100644
index 430c14c..0000000
--- a/android/src/com/levien/synthesizer/android/widgets/waveform/WaveformView.java
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.android.widgets.waveform;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.View;
-import com.levien.synthesizer.core.model.WaveformInput;
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
-import com.levien.synthesizer.core.model.composite.Presets.Setting;
-
-/**
- * WaveformView is a control for selecting from among available waveforms.
- * It's designed to occupy the same space as a KnobView.
- */
-public class WaveformView extends View {
- /** Basic constructor for an Android widget. */
- public WaveformView(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- waveform_ = WaveformInput.SINE;
-
- // Set up the drawing structures.
- paint_ = new Paint();
- path_ = new Path();
- rect_ = new Rect();
-
- // The listener has to be set later.
- listener_ = null;
-
- setPadding(3, 3, 3, 3);
- }
-
- /**
- * Touch event handler.
- */
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- int action = event.getAction();
- switch (action) {
- case MotionEvent.ACTION_DOWN: {
- getDrawingRect(rect_);
- double x = (event.getX() - rect_.left) / rect_.width();
- double y = (event.getY() - rect_.top) / rect_.height();
- if (x < 0.5) {
- if (y < 0.34) {
- setWaveform(WaveformInput.SINE);
- } else if (y < 0.67) {
- setWaveform(WaveformInput.TRIANGLE);
- } else {
- setWaveform(WaveformInput.SQUARE);
- }
- } else {
- if (y < 0.34) {
- setWaveform(WaveformInput.SAWTOOTH);
- } else if (y < 0.67) {
- setWaveform(WaveformInput.NOISE);
- }
- }
- invalidate();
- break;
- }
-
- case MotionEvent.ACTION_MOVE: {
- break;
- }
-
- case MotionEvent.ACTION_UP: {
- break;
- }
- }
- return true;
- }
-
- /**
- * Sets the listener to receive events when the value changes.
- */
- public void setWaveformListener(WaveformListener listener) {
- listener_ = listener;
- }
-
- /**
- * Sets the current value of the knob.
- */
- public void setWaveform(String waveform) {
- waveform_ = waveform;
- if (listener_ != null) {
- listener_.onWaveformChanged(waveform);
- }
- invalidate();
- }
-
- /**
- * Returns the current value of the knob.
- */
- public String getWaveform() {
- return waveform_;
- }
-
- /**
- * Draws a button for selecting a sine waveform.
- */
- protected void drawSine(Canvas canvas,
- float x, float y,
- float width, float height,
- float margin,
- float lineWidth) {
- int steps = 12;
-
- // Sine wave.
- path_.reset();
- path_.moveTo(x, y + (height / 2));
- for (int i = 0; i < steps + 1; i++) {
- float x1 = x + (i / (float)steps) * width;
- float y1 = y + -1 * (height/2) * (float)Math.sin(2.0f/steps * Math.PI * i) + height/2;
- path_.lineTo(x1, y1);
- }
- paint_.setColor(Color.WHITE);
- if (waveform_.equals(WaveformInput.SINE)) {
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(x - margin / 2,
- y - margin / 2,
- x + width + margin / 2,
- y + height + margin / 2,
- paint_);
- paint_.setColor(Color.BLACK);
- }
- paint_.setStyle(Paint.Style.STROKE);
- paint_.setStrokeWidth(lineWidth);
- paint_.setStrokeJoin(Paint.Join.ROUND);
- canvas.drawPath(path_, paint_);
- }
-
- /**
- * Draws a button for selecting a triangle waveform.
- */
- protected void drawTriangle(Canvas canvas,
- float x, float y,
- float width, float height,
- float margin,
- float lineWidth) {
- // Triangle Wave.
- path_.reset();
- path_.moveTo(x, y + (height / 2));
- path_.lineTo(x + width / 4, y);
- path_.lineTo(x + width * (3.0f / 4.0f), y + height);
- path_.lineTo(x + width, y + (height / 2));
- paint_.setColor(Color.WHITE);
- if (waveform_.equals(WaveformInput.TRIANGLE)) {
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(x - margin / 2,
- y - margin / 2,
- x + width + margin / 2,
- y + height + margin / 2,
- paint_);
- paint_.setColor(Color.BLACK);
- }
- paint_.setStyle(Paint.Style.STROKE);
- paint_.setStrokeWidth(lineWidth);
- paint_.setStrokeJoin(Paint.Join.ROUND);
- canvas.drawPath(path_, paint_);
- }
-
- /**
- * Draws a button for selecting a square waveform.
- */
- protected void drawSquare(Canvas canvas,
- float x, float y,
- float width, float height,
- float margin,
- float lineWidth) {
- // Square Wave.
- path_.reset();
- path_.moveTo(x, y + height);
- path_.lineTo(x + width / 4, y + height);
- path_.lineTo(x + width / 4, y);
- path_.lineTo(x + width * (3.0f / 4.0f), y);
- path_.lineTo(x + width * (3.0f / 4.0f), y + height);
- path_.lineTo(x + width, y + height);
- paint_.setColor(Color.WHITE);
- if (waveform_.equals(WaveformInput.SQUARE)) {
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(x - margin / 2,
- y - margin / 2,
- x + width + margin / 2,
- y + height + margin / 2,
- paint_);
- paint_.setColor(Color.BLACK);
- }
- paint_.setStyle(Paint.Style.STROKE);
- paint_.setStrokeWidth(lineWidth);
- paint_.setStrokeJoin(Paint.Join.ROUND);
- canvas.drawPath(path_, paint_);
- }
-
- /**
- * Draws a button for selecting a sawtooth waveform.
- */
- protected void drawSawtooth(Canvas canvas,
- float x, float y,
- float width, float height,
- float margin,
- float lineWidth) {
- // Sawtooth Wave.
- path_.reset();
- path_.moveTo(x, y + height);
- path_.lineTo(x, y);
- path_.lineTo(x + width / 2, y + height);
- path_.lineTo(x + width / 2, y);
- path_.lineTo(x + width, y + height);
- paint_.setColor(Color.WHITE);
- if (waveform_.equals(WaveformInput.SAWTOOTH)) {
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(x - margin / 2,
- y - margin / 2,
- x + width + margin / 2,
- y + height + margin / 2,
- paint_);
- paint_.setColor(Color.BLACK);
- }
- paint_.setStyle(Paint.Style.STROKE);
- paint_.setStrokeWidth(lineWidth);
- paint_.setStrokeJoin(Paint.Join.ROUND);
- canvas.drawPath(path_, paint_);
- }
-
- /**
- * Draws a button for selecting a noise waveform.
- */
- protected void drawNoise(Canvas canvas,
- float x, float y,
- float width, float height,
- float margin,
- float lineWidth) {
- // Noise.
- path_.reset();
- path_.moveTo(x, y + height * 0.5f);
- path_.lineTo(x + 0.125f * width, y + height * 0.4f);
- path_.lineTo(x + 0.25f * width, y + height * 1.0f);
- path_.lineTo(x + 0.375f * width, y + height * 0.3f);
- path_.lineTo(x + 0.5f * width, y + height * 0.7f);
- path_.lineTo(x + 0.625f * width, y + height * 0.0f);
- path_.lineTo(x + 0.75f * width, y + height * 0.8f);
- path_.lineTo(x + 0.875f * width, y + height * 0.2f);
- path_.lineTo(x + 1.0f * width, y + height * 0.5f);
- paint_.setColor(Color.WHITE);
- if (waveform_.equals(WaveformInput.NOISE)) {
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(x - margin / 2,
- y - margin / 2,
- x + width + margin / 2,
- y + height + margin / 2,
- paint_);
- paint_.setColor(Color.BLACK);
- }
- paint_.setStyle(Paint.Style.STROKE);
- paint_.setStrokeWidth(lineWidth);
- paint_.setStrokeJoin(Paint.Join.ROUND);
- canvas.drawPath(path_, paint_);
- }
-
- /**
- * Draws a button for selecting a Karplus-Strong waveform.
- */
- protected void drawOther(Canvas canvas,
- float x, float y,
- float width, float height,
- float margin,
- float lineWidth) {
- int steps = 12;
-
- paint_.setColor(Color.WHITE);
- if (!waveform_.equals(WaveformInput.SINE) &&
- !waveform_.equals(WaveformInput.TRIANGLE) &&
- !waveform_.equals(WaveformInput.SAWTOOTH) &&
- !waveform_.equals(WaveformInput.SQUARE) &&
- !waveform_.equals(WaveformInput.NOISE)) {
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(x - margin / 2,
- y - margin / 2,
- x + width + margin / 2,
- y + height + margin / 2,
- paint_);
- paint_.setColor(Color.BLACK);
- }
- paint_.setStyle(Paint.Style.STROKE);
- paint_.setStrokeWidth(lineWidth);
- paint_.setStrokeJoin(Paint.Join.ROUND);
-
- path_.reset();
- path_.moveTo(x, y + (height / 2));
- for (int i = 0; i < steps + 1; i++) {
- float x1 = x + (i / (float)steps) * width;
- float y1 = y + -1 * (height/2) * (float)Math.sin(2.0f/steps * Math.PI * i) + height/2;
- path_.lineTo(x1, y1);
- }
- canvas.drawPath(path_, paint_);
-
- path_.reset();
- path_.moveTo(x, y + (height / 2));
- for (int i = 0; i < steps + 1; i++) {
- float x1 = x + (i / (float)steps) * width;
- float y1 = y + -0.6f * (height/2) * (float)Math.sin(2.0f/steps * Math.PI * (steps-i)) + height/2;
- path_.lineTo(x1, y1);
- }
- canvas.drawPath(path_, paint_);
- }
-
- /**
- * Drawing handler.
- */
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- getDrawingRect(rect_);
- rect_.set(rect_);
- // Make it square.
- if (rect_.height() > rect_.width()) {
- int center = rect_.centerY();
- rect_.top = center - rect_.width() / 2;
- rect_.bottom = center + rect_.width() / 2;
- } else {
- int center = rect_.centerX();
- rect_.left = center - rect_.height() / 2;
- rect_.right = center + rect_.height() / 2;
- }
-
- paint_.setColor(Color.BLACK);
- paint_.setStyle(Paint.Style.FILL);
- canvas.drawRect(rect_, paint_);
-
- // Draw waveforms.
- float lineWidth = 5.0f;
- float margin = 15.0f;
- float waveWidth = (rect_.width() - 3.0f * margin) / 2.0f;
- float waveHeight = (rect_.height() - 4.0f * margin) / 3.0f;
-
- float xOffset = margin;
- float yOffset = margin;
- drawSine(canvas, xOffset, yOffset, waveWidth, waveHeight, margin, lineWidth);
- yOffset += waveHeight;
- yOffset += margin;
- drawTriangle(canvas, xOffset, yOffset, waveWidth, waveHeight, margin, lineWidth);
- yOffset += waveHeight;
- yOffset += margin;
- drawSquare(canvas, xOffset, yOffset, waveWidth, waveHeight, margin, lineWidth);
- yOffset = margin;
- xOffset += waveWidth;
- xOffset += margin;
- drawSawtooth(canvas, xOffset, yOffset, waveWidth, waveHeight, margin, lineWidth);
- yOffset += waveHeight;
- yOffset += margin;
- drawNoise(canvas, xOffset, yOffset, waveWidth, waveHeight, margin, lineWidth);
- yOffset += waveHeight;
- yOffset += margin;
- drawOther(canvas, xOffset, yOffset, waveWidth, waveHeight, margin, lineWidth);
- }
-
- /**
- * Controls how the knob is sized; it is square, and prefers to be 100x100 pixels.
- */
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-
- // Specify that 100 is preferred for both dimensions.
- int width = 0;
- int height = 0;
- switch (widthMode) {
- case MeasureSpec.EXACTLY:
- width = widthSize;
- break;
- case MeasureSpec.AT_MOST:
- width = widthSize;
- break;
- case MeasureSpec.UNSPECIFIED:
- width = 100;
- break;
- }
- switch (heightMode) {
- case MeasureSpec.EXACTLY:
- height = heightSize;
- break;
- case MeasureSpec.AT_MOST:
- height = heightSize;
- break;
- case MeasureSpec.UNSPECIFIED:
- height = 100;
- break;
- }
-
- // Make it square.
- if (width > height && widthMode != MeasureSpec.EXACTLY) {
- width = height;
- }
- if (height > width && heightMode != MeasureSpec.EXACTLY) {
- height = width;
- }
-
- setMeasuredDimension(width, height);
- }
-
- /**
- * Connects control to a WaveformInput.
- * @input - The synthesizer input to connect to.
- */
- public void bindTo(WaveformInput waveform) {
- input_ = waveform;
- setWaveform(waveform.getWaveform(waveform.getSelected()));
- setWaveformListener(new WaveformListener() {
- public void onWaveformChanged(String newValue) {
- input_.select(newValue);
- }
- });
- }
-
- /**
- * Connects control to a WaveformSelector module.
- * @synth - The synthesizer to connect to.
- * @setting - The setting to connect to.
- * @return - True on success, false on failure.
- */
- public boolean bindTo(final MultiChannelSynthesizer synth, int channel, Setting setting) {
- WaveformInput input = synth.getChannel(0).getWaveformInput(setting);
- if (input != null) {
- bindTo(input);
- return true;
- } else {
- Log.e(getClass().getName(), "Unable to bind to setting " + setting.name() + ".");
- return false;
- }
- }
-
- // Currently selected waveform.
- private String waveform_;
- protected WaveformInput input_;
-
- // Structures used in drawing that we don't want to reallocate every time we draw.
- protected Paint paint_;
- protected Path path_;
- protected Rect rect_;
-
- // Object listening for events when the knob's value changes.
- private WaveformListener listener_;
-}
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000..d158a9e
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,41 @@
+apply plugin: 'com.android.model.application'
+
+model {
+ android {
+ compileSdkVersion 23
+ buildToolsVersion "23.0.3"
+
+ defaultConfig {
+ applicationId "com.levien.synthesizer"
+ minSdkVersion.apiLevel 16
+ targetSdkVersion.apiLevel 23
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles.add(file('proguard-android.txt'))
+ }
+ }
+ ndk {
+ moduleName "synth"
+ ldLibs.addAll(['log', 'OpenSLES'])
+ }
+ sources {
+ main {
+ jni {
+ source {
+ excludes.addAll(["main.cc", "wavout.cc", "test_*.cc", "SynthApp/*"])
+ }
+ }
+ }
+ }
+ }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ testCompile 'junit:junit:4.12'
+ compile 'com.android.support:appcompat-v7:23.4.0'
+}
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..0b51b5f
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/raph/Library/Android/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/app/src/androidTest/java/com/levien/synthesizer/ApplicationTest.java b/app/src/androidTest/java/com/levien/synthesizer/ApplicationTest.java
new file mode 100644
index 0000000..12634bc
--- /dev/null
+++ b/app/src/androidTest/java/com/levien/synthesizer/ApplicationTest.java
@@ -0,0 +1,13 @@
+package com.levien.synthesizer;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * Testing Fundamentals
+ */
+public class ApplicationTest extends ApplicationTestCase {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..f1b60d7
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/src/com/levien/synthesizer/android/AndroidGlue.java b/app/src/main/java/com/levien/synthesizer/android/AndroidGlue.java
similarity index 100%
rename from android/src/com/levien/synthesizer/android/AndroidGlue.java
rename to app/src/main/java/com/levien/synthesizer/android/AndroidGlue.java
diff --git a/android/src/com/levien/synthesizer/android/service/SynthesizerService.java b/app/src/main/java/com/levien/synthesizer/android/service/SynthesizerService.java
similarity index 97%
rename from android/src/com/levien/synthesizer/android/service/SynthesizerService.java
rename to app/src/main/java/com/levien/synthesizer/android/service/SynthesizerService.java
index e17c3b6..1aa7e42 100755
--- a/android/src/com/levien/synthesizer/android/service/SynthesizerService.java
+++ b/app/src/main/java/com/levien/synthesizer/android/service/SynthesizerService.java
@@ -43,7 +43,6 @@ import com.levien.synthesizer.android.AndroidGlue;
import com.levien.synthesizer.android.usb.UsbMidiDevice;
import com.levien.synthesizer.core.midi.MessageTee;
import com.levien.synthesizer.core.midi.MidiListener;
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
/**
* An Android Service that plays audio from a synthesizer.
@@ -56,15 +55,6 @@ public class SynthesizerService extends Service {
public SynthesizerService getService() {
return SynthesizerService.this;
}
-
- /**
- * Gets the underlying synthesizer powering this service.
- *
- * Obsolete, to be deleted.
- */
- public MultiChannelSynthesizer getSynthesizer() {
- return null;
- }
}
/**
diff --git a/android/src/com/levien/synthesizer/android/service/SynthesizerThread.java b/app/src/main/java/com/levien/synthesizer/android/service/SynthesizerThread.java
similarity index 90%
rename from android/src/com/levien/synthesizer/android/service/SynthesizerThread.java
rename to app/src/main/java/com/levien/synthesizer/android/service/SynthesizerThread.java
index ca1e816..a6765ce 100755
--- a/android/src/com/levien/synthesizer/android/service/SynthesizerThread.java
+++ b/app/src/main/java/com/levien/synthesizer/android/service/SynthesizerThread.java
@@ -14,14 +14,14 @@
* limitations under the License.
*/
+// This class is probably obsolete and should be deleted
+
package com.levien.synthesizer.android.service;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.util.Log;
-import com.levien.synthesizer.core.model.SynthesisTime;
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
/**
* SynthesizerThread is a thread-safe interface to a thread that constantly plays sampled audio data
@@ -30,18 +30,14 @@ import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
public class SynthesizerThread {
/**
* Creates a new SynthesizerThread that will play audio from synthesizer.
- * @param synthesizer - the source of the audio data to output.
*/
- public SynthesizerThread(MultiChannelSynthesizer synthesizer, int sampleRateInHz) {
+ public SynthesizerThread(int sampleRateInHz) {
playingLock_ = new Object();
playing_ = false;
shouldDie_ = false;
audioTrackLock_ = new Object();
audioTrack_ = null;
- synthesizer_ = synthesizer;
sampleRateInHz_ = sampleRateInHz;
- time_ = new SynthesisTime();
- time_.setSampleRate(sampleRateInHz);
}
/**
@@ -141,7 +137,6 @@ public class SynthesizerThread {
bufferSizeInBytes, // int bufferSizeInBytes,
AudioTrack.MODE_STREAM); // int mode);
buffer_ = new short[bufferSizeInBytes / 8];
- time_.reset();
}
}
@@ -177,7 +172,7 @@ public class SynthesizerThread {
for (int i = 0; i < buffer_.length; ++i) {
// Change the output range from [-1, 1] to [-32767, 32767].
// 16-bit signed output is fairly standard, and hard-coded.
- double output = synthesizer_.getValue(time_);
+ double output = 0;
// Clamp values out of range.
if (output < -1.0) {
output = -1.0;
@@ -186,7 +181,6 @@ public class SynthesizerThread {
output = 1.0;
}
buffer_[i] = (short)(32767 * output);
- time_.advance();
}
synchronized (audioTrackLock_) {
if (audioTrack_ != null) {
@@ -221,10 +215,4 @@ public class SynthesizerThread {
// The sample rate of the synthesizer.
private int sampleRateInHz_;
-
- // Tracker for time since synthesis started.
- private SynthesisTime time_;
-
- // Module to provide sampled audio data to be output.
- private MultiChannelSynthesizer synthesizer_;
}
diff --git a/android/src/com/levien/synthesizer/android/stats/JitterStats.java b/app/src/main/java/com/levien/synthesizer/android/stats/JitterStats.java
similarity index 100%
rename from android/src/com/levien/synthesizer/android/stats/JitterStats.java
rename to app/src/main/java/com/levien/synthesizer/android/stats/JitterStats.java
diff --git a/android/src/com/levien/synthesizer/android/ui/PianoActivity2.java b/app/src/main/java/com/levien/synthesizer/android/ui/PianoActivity2.java
similarity index 99%
rename from android/src/com/levien/synthesizer/android/ui/PianoActivity2.java
rename to app/src/main/java/com/levien/synthesizer/android/ui/PianoActivity2.java
index 26da9c0..0008473 100644
--- a/android/src/com/levien/synthesizer/android/ui/PianoActivity2.java
+++ b/app/src/main/java/com/levien/synthesizer/android/ui/PianoActivity2.java
@@ -89,9 +89,11 @@ public class PianoActivity2 extends SynthActivity implements OnSharedPreferenceC
case R.id.settings:
startActivity(new Intent(this, SettingsActivity.class));
return true;
+ /*
case R.id.compose:
startActivity(new Intent(this, ScoreActivity.class));
return true;
+ */
default:
return super.onOptionsItemSelected(item);
}
diff --git a/android/src/com/levien/synthesizer/android/ui/SettingsActivity.java b/app/src/main/java/com/levien/synthesizer/android/ui/SettingsActivity.java
similarity index 100%
rename from android/src/com/levien/synthesizer/android/ui/SettingsActivity.java
rename to app/src/main/java/com/levien/synthesizer/android/ui/SettingsActivity.java
diff --git a/android/src/com/levien/synthesizer/android/ui/SynthActivity.java b/app/src/main/java/com/levien/synthesizer/android/ui/SynthActivity.java
similarity index 100%
rename from android/src/com/levien/synthesizer/android/ui/SynthActivity.java
rename to app/src/main/java/com/levien/synthesizer/android/ui/SynthActivity.java
diff --git a/android/src/com/levien/synthesizer/android/usb/UsbMidiDevice.java b/app/src/main/java/com/levien/synthesizer/android/usb/UsbMidiDevice.java
similarity index 100%
rename from android/src/com/levien/synthesizer/android/usb/UsbMidiDevice.java
rename to app/src/main/java/com/levien/synthesizer/android/usb/UsbMidiDevice.java
diff --git a/android/src/com/levien/synthesizer/android/widgets/keyboard/KeySpec.java b/app/src/main/java/com/levien/synthesizer/android/widgets/keyboard/KeySpec.java
similarity index 100%
rename from android/src/com/levien/synthesizer/android/widgets/keyboard/KeySpec.java
rename to app/src/main/java/com/levien/synthesizer/android/widgets/keyboard/KeySpec.java
diff --git a/android/src/com/levien/synthesizer/android/widgets/keyboard/KeyboardSpec.java b/app/src/main/java/com/levien/synthesizer/android/widgets/keyboard/KeyboardSpec.java
similarity index 100%
rename from android/src/com/levien/synthesizer/android/widgets/keyboard/KeyboardSpec.java
rename to app/src/main/java/com/levien/synthesizer/android/widgets/keyboard/KeyboardSpec.java
diff --git a/android/src/com/levien/synthesizer/android/widgets/keyboard/KeyboardView.java b/app/src/main/java/com/levien/synthesizer/android/widgets/keyboard/KeyboardView.java
similarity index 100%
rename from android/src/com/levien/synthesizer/android/widgets/keyboard/KeyboardView.java
rename to app/src/main/java/com/levien/synthesizer/android/widgets/keyboard/KeyboardView.java
diff --git a/android/src/com/levien/synthesizer/android/widgets/keyboard/ScrollStripView.java b/app/src/main/java/com/levien/synthesizer/android/widgets/keyboard/ScrollStripView.java
similarity index 100%
rename from android/src/com/levien/synthesizer/android/widgets/keyboard/ScrollStripView.java
rename to app/src/main/java/com/levien/synthesizer/android/widgets/keyboard/ScrollStripView.java
diff --git a/android/src/com/levien/synthesizer/android/widgets/knob/KnobListener.java b/app/src/main/java/com/levien/synthesizer/android/widgets/knob/KnobListener.java
similarity index 100%
rename from android/src/com/levien/synthesizer/android/widgets/knob/KnobListener.java
rename to app/src/main/java/com/levien/synthesizer/android/widgets/knob/KnobListener.java
diff --git a/android/src/com/levien/synthesizer/android/widgets/knob/KnobPlaceholderView.java b/app/src/main/java/com/levien/synthesizer/android/widgets/knob/KnobPlaceholderView.java
similarity index 100%
rename from android/src/com/levien/synthesizer/android/widgets/knob/KnobPlaceholderView.java
rename to app/src/main/java/com/levien/synthesizer/android/widgets/knob/KnobPlaceholderView.java
diff --git a/android/src/com/levien/synthesizer/android/widgets/knob/KnobPreference.java b/app/src/main/java/com/levien/synthesizer/android/widgets/knob/KnobPreference.java
similarity index 100%
rename from android/src/com/levien/synthesizer/android/widgets/knob/KnobPreference.java
rename to app/src/main/java/com/levien/synthesizer/android/widgets/knob/KnobPreference.java
diff --git a/android/src/com/levien/synthesizer/android/widgets/knob/KnobView.java b/app/src/main/java/com/levien/synthesizer/android/widgets/knob/KnobView.java
similarity index 88%
rename from android/src/com/levien/synthesizer/android/widgets/knob/KnobView.java
rename to app/src/main/java/com/levien/synthesizer/android/widgets/knob/KnobView.java
index ece5e14..7f95c16 100644
--- a/android/src/com/levien/synthesizer/android/widgets/knob/KnobView.java
+++ b/app/src/main/java/com/levien/synthesizer/android/widgets/knob/KnobView.java
@@ -34,9 +34,6 @@ import android.view.MotionEvent;
import android.view.View;
import com.levien.synthesizer.R;
-import com.levien.synthesizer.core.model.SynthesizerInput;
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
-import com.levien.synthesizer.core.model.composite.Presets.Setting;
/**
* KnobView is a widget for setting a real value by turning a virtual "knob".
@@ -262,36 +259,6 @@ public class KnobView extends View {
setMeasuredDimension(width, height);
}
- /**
- * Connects knob to a SynthesizerInput.
- * @input - The synthesizer input to connect to.
- */
- public void bindTo(final SynthesizerInput input) {
- setValue(input.getSynthesizerInputValue());
- setKnobListener(new KnobListener() {
- public void onKnobChanged(double newValue) {
- input.setValue(newValue);
- }
- });
- }
-
- /**
- * Connects knob to a SynthesizerInput.
- * @synth - The synthesizer to connect to.
- * @path - The setting to connect to.
- * @return - True on success, false on failure.
- */
- public boolean bindTo(final MultiChannelSynthesizer synth, int channel, Setting setting) {
- SynthesizerInput input = synth.getChannel(channel).getSynthesizerInput(setting);
- if (input != null) {
- bindTo(input);
- return true;
- } else {
- Log.e(getClass().getName(), "Unable to bind to setting " + setting.name() + ".");
- return false;
- }
- }
-
// Knob's current value, ranges from 0 - 1.0.
private double knobValue_;
private double min_;
diff --git a/core/src/com/levien/synthesizer/core/midi/MessageFromBytes.java b/app/src/main/java/com/levien/synthesizer/core/midi/MessageFromBytes.java
similarity index 100%
rename from core/src/com/levien/synthesizer/core/midi/MessageFromBytes.java
rename to app/src/main/java/com/levien/synthesizer/core/midi/MessageFromBytes.java
diff --git a/core/src/com/levien/synthesizer/core/midi/MessageInputProcessor.java b/app/src/main/java/com/levien/synthesizer/core/midi/MessageInputProcessor.java
similarity index 100%
rename from core/src/com/levien/synthesizer/core/midi/MessageInputProcessor.java
rename to app/src/main/java/com/levien/synthesizer/core/midi/MessageInputProcessor.java
diff --git a/core/src/com/levien/synthesizer/core/midi/MessageOutputProcessor.java b/app/src/main/java/com/levien/synthesizer/core/midi/MessageOutputProcessor.java
similarity index 100%
rename from core/src/com/levien/synthesizer/core/midi/MessageOutputProcessor.java
rename to app/src/main/java/com/levien/synthesizer/core/midi/MessageOutputProcessor.java
diff --git a/core/src/com/levien/synthesizer/core/midi/MessageTee.java b/app/src/main/java/com/levien/synthesizer/core/midi/MessageTee.java
similarity index 100%
rename from core/src/com/levien/synthesizer/core/midi/MessageTee.java
rename to app/src/main/java/com/levien/synthesizer/core/midi/MessageTee.java
diff --git a/core/src/com/levien/synthesizer/core/midi/MidiAdapter.java b/app/src/main/java/com/levien/synthesizer/core/midi/MidiAdapter.java
similarity index 100%
rename from core/src/com/levien/synthesizer/core/midi/MidiAdapter.java
rename to app/src/main/java/com/levien/synthesizer/core/midi/MidiAdapter.java
diff --git a/core/src/com/levien/synthesizer/core/midi/MidiChannelFilter.java b/app/src/main/java/com/levien/synthesizer/core/midi/MidiChannelFilter.java
similarity index 100%
rename from core/src/com/levien/synthesizer/core/midi/MidiChannelFilter.java
rename to app/src/main/java/com/levien/synthesizer/core/midi/MidiChannelFilter.java
diff --git a/core/src/com/levien/synthesizer/core/midi/MidiEvent.java b/app/src/main/java/com/levien/synthesizer/core/midi/MidiEvent.java
similarity index 100%
rename from core/src/com/levien/synthesizer/core/midi/MidiEvent.java
rename to app/src/main/java/com/levien/synthesizer/core/midi/MidiEvent.java
diff --git a/core/src/com/levien/synthesizer/core/midi/MidiFile.java b/app/src/main/java/com/levien/synthesizer/core/midi/MidiFile.java
similarity index 100%
rename from core/src/com/levien/synthesizer/core/midi/MidiFile.java
rename to app/src/main/java/com/levien/synthesizer/core/midi/MidiFile.java
diff --git a/core/src/com/levien/synthesizer/core/midi/MidiFilePlayer.java b/app/src/main/java/com/levien/synthesizer/core/midi/MidiFilePlayer.java
similarity index 100%
rename from core/src/com/levien/synthesizer/core/midi/MidiFilePlayer.java
rename to app/src/main/java/com/levien/synthesizer/core/midi/MidiFilePlayer.java
diff --git a/core/src/com/levien/synthesizer/core/midi/MidiHeader.java b/app/src/main/java/com/levien/synthesizer/core/midi/MidiHeader.java
similarity index 100%
rename from core/src/com/levien/synthesizer/core/midi/MidiHeader.java
rename to app/src/main/java/com/levien/synthesizer/core/midi/MidiHeader.java
diff --git a/core/src/com/levien/synthesizer/core/midi/MidiListener.java b/app/src/main/java/com/levien/synthesizer/core/midi/MidiListener.java
similarity index 100%
rename from core/src/com/levien/synthesizer/core/midi/MidiListener.java
rename to app/src/main/java/com/levien/synthesizer/core/midi/MidiListener.java
diff --git a/core/src/com/levien/synthesizer/core/midi/MidiListenerProxy.java b/app/src/main/java/com/levien/synthesizer/core/midi/MidiListenerProxy.java
similarity index 100%
rename from core/src/com/levien/synthesizer/core/midi/MidiListenerProxy.java
rename to app/src/main/java/com/levien/synthesizer/core/midi/MidiListenerProxy.java
diff --git a/core/src/com/levien/synthesizer/core/midi/MidiReader.java b/app/src/main/java/com/levien/synthesizer/core/midi/MidiReader.java
similarity index 100%
rename from core/src/com/levien/synthesizer/core/midi/MidiReader.java
rename to app/src/main/java/com/levien/synthesizer/core/midi/MidiReader.java
diff --git a/core/src/com/levien/synthesizer/core/midi/MidiTrack.java b/app/src/main/java/com/levien/synthesizer/core/midi/MidiTrack.java
similarity index 100%
rename from core/src/com/levien/synthesizer/core/midi/MidiTrack.java
rename to app/src/main/java/com/levien/synthesizer/core/midi/MidiTrack.java
diff --git a/core/src/com/levien/synthesizer/core/midi/MidiUtil.java b/app/src/main/java/com/levien/synthesizer/core/midi/MidiUtil.java
similarity index 100%
rename from core/src/com/levien/synthesizer/core/midi/MidiUtil.java
rename to app/src/main/java/com/levien/synthesizer/core/midi/MidiUtil.java
diff --git a/cpp/src/SynthApp.gyp b/app/src/main/jni/SynthApp.gyp
similarity index 100%
rename from cpp/src/SynthApp.gyp
rename to app/src/main/jni/SynthApp.gyp
diff --git a/cpp/src/SynthApp.xcodeproj/project.pbxproj b/app/src/main/jni/SynthApp.xcodeproj/project.pbxproj
similarity index 100%
rename from cpp/src/SynthApp.xcodeproj/project.pbxproj
rename to app/src/main/jni/SynthApp.xcodeproj/project.pbxproj
diff --git a/cpp/src/SynthApp/English.lproj/InfoPlist.strings b/app/src/main/jni/SynthApp/English.lproj/InfoPlist.strings
similarity index 100%
rename from cpp/src/SynthApp/English.lproj/InfoPlist.strings
rename to app/src/main/jni/SynthApp/English.lproj/InfoPlist.strings
diff --git a/cpp/src/SynthApp/English.lproj/MainMenu.xib b/app/src/main/jni/SynthApp/English.lproj/MainMenu.xib
similarity index 100%
rename from cpp/src/SynthApp/English.lproj/MainMenu.xib
rename to app/src/main/jni/SynthApp/English.lproj/MainMenu.xib
diff --git a/cpp/src/SynthApp/Synth-Info.plist b/app/src/main/jni/SynthApp/Synth-Info.plist
similarity index 100%
rename from cpp/src/SynthApp/Synth-Info.plist
rename to app/src/main/jni/SynthApp/Synth-Info.plist
diff --git a/cpp/src/SynthApp/SynthAppDelegate.h b/app/src/main/jni/SynthApp/SynthAppDelegate.h
similarity index 100%
rename from cpp/src/SynthApp/SynthAppDelegate.h
rename to app/src/main/jni/SynthApp/SynthAppDelegate.h
diff --git a/cpp/src/SynthApp/SynthAppDelegate.mm b/app/src/main/jni/SynthApp/SynthAppDelegate.mm
similarity index 100%
rename from cpp/src/SynthApp/SynthAppDelegate.mm
rename to app/src/main/jni/SynthApp/SynthAppDelegate.mm
diff --git a/cpp/src/SynthApp/SynthApp_Prefix.pch b/app/src/main/jni/SynthApp/SynthApp_Prefix.pch
similarity index 100%
rename from cpp/src/SynthApp/SynthApp_Prefix.pch
rename to app/src/main/jni/SynthApp/SynthApp_Prefix.pch
diff --git a/cpp/src/SynthApp/SynthMain.h b/app/src/main/jni/SynthApp/SynthMain.h
similarity index 100%
rename from cpp/src/SynthApp/SynthMain.h
rename to app/src/main/jni/SynthApp/SynthMain.h
diff --git a/cpp/src/SynthApp/SynthMain.mm b/app/src/main/jni/SynthApp/SynthMain.mm
similarity index 100%
rename from cpp/src/SynthApp/SynthMain.mm
rename to app/src/main/jni/SynthApp/SynthMain.mm
diff --git a/cpp/src/SynthApp/main.m b/app/src/main/jni/SynthApp/main.m
similarity index 100%
rename from cpp/src/SynthApp/main.m
rename to app/src/main/jni/SynthApp/main.m
diff --git a/cpp/src/SynthApp/midi_in_mac.cc b/app/src/main/jni/SynthApp/midi_in_mac.cc
similarity index 100%
rename from cpp/src/SynthApp/midi_in_mac.cc
rename to app/src/main/jni/SynthApp/midi_in_mac.cc
diff --git a/cpp/src/SynthApp/midi_in_mac.h b/app/src/main/jni/SynthApp/midi_in_mac.h
similarity index 100%
rename from cpp/src/SynthApp/midi_in_mac.h
rename to app/src/main/jni/SynthApp/midi_in_mac.h
diff --git a/cpp/src/aligned_buf.h b/app/src/main/jni/aligned_buf.h
similarity index 100%
rename from cpp/src/aligned_buf.h
rename to app/src/main/jni/aligned_buf.h
diff --git a/cpp/src/android_glue.cc b/app/src/main/jni/android_glue.cc
similarity index 100%
rename from cpp/src/android_glue.cc
rename to app/src/main/jni/android_glue.cc
diff --git a/cpp/src/controllers.h b/app/src/main/jni/controllers.h
similarity index 100%
rename from cpp/src/controllers.h
rename to app/src/main/jni/controllers.h
diff --git a/cpp/src/core.gyp b/app/src/main/jni/core.gyp
similarity index 100%
rename from cpp/src/core.gyp
rename to app/src/main/jni/core.gyp
diff --git a/cpp/src/core.xcodeproj/project.pbxproj b/app/src/main/jni/core.xcodeproj/project.pbxproj
similarity index 100%
rename from cpp/src/core.xcodeproj/project.pbxproj
rename to app/src/main/jni/core.xcodeproj/project.pbxproj
diff --git a/cpp/src/dx7note.cc b/app/src/main/jni/dx7note.cc
similarity index 100%
rename from cpp/src/dx7note.cc
rename to app/src/main/jni/dx7note.cc
diff --git a/cpp/src/dx7note.h b/app/src/main/jni/dx7note.h
similarity index 100%
rename from cpp/src/dx7note.h
rename to app/src/main/jni/dx7note.h
diff --git a/cpp/src/env.cc b/app/src/main/jni/env.cc
similarity index 100%
rename from cpp/src/env.cc
rename to app/src/main/jni/env.cc
diff --git a/cpp/src/env.h b/app/src/main/jni/env.h
similarity index 100%
rename from cpp/src/env.h
rename to app/src/main/jni/env.h
diff --git a/cpp/src/exp2.cc b/app/src/main/jni/exp2.cc
similarity index 100%
rename from cpp/src/exp2.cc
rename to app/src/main/jni/exp2.cc
diff --git a/cpp/src/exp2.h b/app/src/main/jni/exp2.h
similarity index 100%
rename from cpp/src/exp2.h
rename to app/src/main/jni/exp2.h
diff --git a/cpp/src/fir.cc b/app/src/main/jni/fir.cc
similarity index 100%
rename from cpp/src/fir.cc
rename to app/src/main/jni/fir.cc
diff --git a/cpp/src/fir.h b/app/src/main/jni/fir.h
similarity index 100%
rename from cpp/src/fir.h
rename to app/src/main/jni/fir.h
diff --git a/cpp/src/fm_core.cc b/app/src/main/jni/fm_core.cc
similarity index 100%
rename from cpp/src/fm_core.cc
rename to app/src/main/jni/fm_core.cc
diff --git a/cpp/src/fm_core.h b/app/src/main/jni/fm_core.h
similarity index 100%
rename from cpp/src/fm_core.h
rename to app/src/main/jni/fm_core.h
diff --git a/cpp/src/fm_op_kernel.cc b/app/src/main/jni/fm_op_kernel.cc
similarity index 100%
rename from cpp/src/fm_op_kernel.cc
rename to app/src/main/jni/fm_op_kernel.cc
diff --git a/cpp/src/fm_op_kernel.h b/app/src/main/jni/fm_op_kernel.h
similarity index 100%
rename from cpp/src/fm_op_kernel.h
rename to app/src/main/jni/fm_op_kernel.h
diff --git a/cpp/src/freqlut.cc b/app/src/main/jni/freqlut.cc
similarity index 100%
rename from cpp/src/freqlut.cc
rename to app/src/main/jni/freqlut.cc
diff --git a/cpp/src/freqlut.h b/app/src/main/jni/freqlut.h
similarity index 100%
rename from cpp/src/freqlut.h
rename to app/src/main/jni/freqlut.h
diff --git a/cpp/src/lfo.cc b/app/src/main/jni/lfo.cc
similarity index 100%
rename from cpp/src/lfo.cc
rename to app/src/main/jni/lfo.cc
diff --git a/cpp/src/lfo.h b/app/src/main/jni/lfo.h
similarity index 100%
rename from cpp/src/lfo.h
rename to app/src/main/jni/lfo.h
diff --git a/cpp/src/log2.cc b/app/src/main/jni/log2.cc
similarity index 100%
rename from cpp/src/log2.cc
rename to app/src/main/jni/log2.cc
diff --git a/cpp/src/log2.h b/app/src/main/jni/log2.h
similarity index 100%
rename from cpp/src/log2.h
rename to app/src/main/jni/log2.h
diff --git a/cpp/src/main.cc b/app/src/main/jni/main.cc
similarity index 100%
rename from cpp/src/main.cc
rename to app/src/main/jni/main.cc
diff --git a/cpp/src/main.gyp b/app/src/main/jni/main.gyp
similarity index 100%
rename from cpp/src/main.gyp
rename to app/src/main/jni/main.gyp
diff --git a/cpp/src/module.h b/app/src/main/jni/module.h
similarity index 100%
rename from cpp/src/module.h
rename to app/src/main/jni/module.h
diff --git a/cpp/src/neon_fir.s b/app/src/main/jni/neon_fir.s
similarity index 100%
rename from cpp/src/neon_fir.s
rename to app/src/main/jni/neon_fir.s
diff --git a/cpp/src/neon_fm_kernel.s b/app/src/main/jni/neon_fm_kernel.s
similarity index 100%
rename from cpp/src/neon_fm_kernel.s
rename to app/src/main/jni/neon_fm_kernel.s
diff --git a/cpp/src/neon_iir.s b/app/src/main/jni/neon_iir.s
similarity index 100%
rename from cpp/src/neon_iir.s
rename to app/src/main/jni/neon_iir.s
diff --git a/cpp/src/neon_ladder.s b/app/src/main/jni/neon_ladder.s
similarity index 100%
rename from cpp/src/neon_ladder.s
rename to app/src/main/jni/neon_ladder.s
diff --git a/cpp/src/patch.cc b/app/src/main/jni/patch.cc
similarity index 100%
rename from cpp/src/patch.cc
rename to app/src/main/jni/patch.cc
diff --git a/cpp/src/patch.h b/app/src/main/jni/patch.h
similarity index 100%
rename from cpp/src/patch.h
rename to app/src/main/jni/patch.h
diff --git a/cpp/src/pitchenv.cc b/app/src/main/jni/pitchenv.cc
similarity index 100%
rename from cpp/src/pitchenv.cc
rename to app/src/main/jni/pitchenv.cc
diff --git a/cpp/src/pitchenv.h b/app/src/main/jni/pitchenv.h
similarity index 100%
rename from cpp/src/pitchenv.h
rename to app/src/main/jni/pitchenv.h
diff --git a/cpp/src/resofilter.cc b/app/src/main/jni/resofilter.cc
similarity index 100%
rename from cpp/src/resofilter.cc
rename to app/src/main/jni/resofilter.cc
diff --git a/cpp/src/resofilter.h b/app/src/main/jni/resofilter.h
similarity index 100%
rename from cpp/src/resofilter.h
rename to app/src/main/jni/resofilter.h
diff --git a/cpp/src/ringbuffer.cc b/app/src/main/jni/ringbuffer.cc
similarity index 100%
rename from cpp/src/ringbuffer.cc
rename to app/src/main/jni/ringbuffer.cc
diff --git a/cpp/src/ringbuffer.h b/app/src/main/jni/ringbuffer.h
similarity index 100%
rename from cpp/src/ringbuffer.h
rename to app/src/main/jni/ringbuffer.h
diff --git a/cpp/src/sawtooth.cc b/app/src/main/jni/sawtooth.cc
similarity index 100%
rename from cpp/src/sawtooth.cc
rename to app/src/main/jni/sawtooth.cc
diff --git a/cpp/src/sawtooth.h b/app/src/main/jni/sawtooth.h
similarity index 100%
rename from cpp/src/sawtooth.h
rename to app/src/main/jni/sawtooth.h
diff --git a/cpp/src/sin.cc b/app/src/main/jni/sin.cc
similarity index 100%
rename from cpp/src/sin.cc
rename to app/src/main/jni/sin.cc
diff --git a/cpp/src/sin.h b/app/src/main/jni/sin.h
similarity index 100%
rename from cpp/src/sin.h
rename to app/src/main/jni/sin.h
diff --git a/cpp/src/synth.h b/app/src/main/jni/synth.h
similarity index 100%
rename from cpp/src/synth.h
rename to app/src/main/jni/synth.h
diff --git a/cpp/src/synth_unit.cc b/app/src/main/jni/synth_unit.cc
similarity index 100%
rename from cpp/src/synth_unit.cc
rename to app/src/main/jni/synth_unit.cc
diff --git a/cpp/src/synth_unit.h b/app/src/main/jni/synth_unit.h
similarity index 100%
rename from cpp/src/synth_unit.h
rename to app/src/main/jni/synth_unit.h
diff --git a/cpp/src/test_filter.cc b/app/src/main/jni/test_filter.cc
similarity index 100%
rename from cpp/src/test_filter.cc
rename to app/src/main/jni/test_filter.cc
diff --git a/cpp/src/test_neon.cc b/app/src/main/jni/test_neon.cc
similarity index 100%
rename from cpp/src/test_neon.cc
rename to app/src/main/jni/test_neon.cc
diff --git a/cpp/src/test_ringbuffer.cc b/app/src/main/jni/test_ringbuffer.cc
similarity index 100%
rename from cpp/src/test_ringbuffer.cc
rename to app/src/main/jni/test_ringbuffer.cc
diff --git a/cpp/src/wavout.cc b/app/src/main/jni/wavout.cc
similarity index 100%
rename from cpp/src/wavout.cc
rename to app/src/main/jni/wavout.cc
diff --git a/cpp/src/wavout.h b/app/src/main/jni/wavout.h
similarity index 100%
rename from cpp/src/wavout.h
rename to app/src/main/jni/wavout.h
diff --git a/android/res/drawable-hdpi/add.png b/app/src/main/res/drawable-hdpi/add.png
similarity index 100%
rename from android/res/drawable-hdpi/add.png
rename to app/src/main/res/drawable-hdpi/add.png
diff --git a/android/res/drawable-hdpi/arrow.png b/app/src/main/res/drawable-hdpi/arrow.png
similarity index 100%
rename from android/res/drawable-hdpi/arrow.png
rename to app/src/main/res/drawable-hdpi/arrow.png
diff --git a/android/res/drawable-hdpi/bass.png b/app/src/main/res/drawable-hdpi/bass.png
similarity index 100%
rename from android/res/drawable-hdpi/bass.png
rename to app/src/main/res/drawable-hdpi/bass.png
diff --git a/android/res/drawable-hdpi/closed_eye.png b/app/src/main/res/drawable-hdpi/closed_eye.png
similarity index 100%
rename from android/res/drawable-hdpi/closed_eye.png
rename to app/src/main/res/drawable-hdpi/closed_eye.png
diff --git a/android/res/drawable-hdpi/down.png b/app/src/main/res/drawable-hdpi/down.png
similarity index 100%
rename from android/res/drawable-hdpi/down.png
rename to app/src/main/res/drawable-hdpi/down.png
diff --git a/android/res/drawable-hdpi/drums.png b/app/src/main/res/drawable-hdpi/drums.png
similarity index 100%
rename from android/res/drawable-hdpi/drums.png
rename to app/src/main/res/drawable-hdpi/drums.png
diff --git a/android/res/drawable-hdpi/eighth_note.png b/app/src/main/res/drawable-hdpi/eighth_note.png
similarity index 100%
rename from android/res/drawable-hdpi/eighth_note.png
rename to app/src/main/res/drawable-hdpi/eighth_note.png
diff --git a/android/res/drawable-hdpi/flute.png b/app/src/main/res/drawable-hdpi/flute.png
similarity index 100%
rename from android/res/drawable-hdpi/flute.png
rename to app/src/main/res/drawable-hdpi/flute.png
diff --git a/android/res/drawable-hdpi/guitar.png b/app/src/main/res/drawable-hdpi/guitar.png
similarity index 100%
rename from android/res/drawable-hdpi/guitar.png
rename to app/src/main/res/drawable-hdpi/guitar.png
diff --git a/android/res/drawable-hdpi/half_note.png b/app/src/main/res/drawable-hdpi/half_note.png
similarity index 100%
rename from android/res/drawable-hdpi/half_note.png
rename to app/src/main/res/drawable-hdpi/half_note.png
diff --git a/android/res/drawable-hdpi/icon.png b/app/src/main/res/drawable-hdpi/icon.png
similarity index 100%
rename from android/res/drawable-hdpi/icon.png
rename to app/src/main/res/drawable-hdpi/icon.png
diff --git a/android/res/drawable-hdpi/loop.png b/app/src/main/res/drawable-hdpi/loop.png
similarity index 100%
rename from android/res/drawable-hdpi/loop.png
rename to app/src/main/res/drawable-hdpi/loop.png
diff --git a/android/res/drawable-hdpi/no_note.png b/app/src/main/res/drawable-hdpi/no_note.png
similarity index 100%
rename from android/res/drawable-hdpi/no_note.png
rename to app/src/main/res/drawable-hdpi/no_note.png
diff --git a/android/res/drawable-hdpi/open_eye.png b/app/src/main/res/drawable-hdpi/open_eye.png
similarity index 100%
rename from android/res/drawable-hdpi/open_eye.png
rename to app/src/main/res/drawable-hdpi/open_eye.png
diff --git a/android/res/drawable-hdpi/play.png b/app/src/main/res/drawable-hdpi/play.png
similarity index 100%
rename from android/res/drawable-hdpi/play.png
rename to app/src/main/res/drawable-hdpi/play.png
diff --git a/android/res/drawable-hdpi/play_piano.png b/app/src/main/res/drawable-hdpi/play_piano.png
similarity index 100%
rename from android/res/drawable-hdpi/play_piano.png
rename to app/src/main/res/drawable-hdpi/play_piano.png
diff --git a/android/res/drawable-hdpi/quarter_note.png b/app/src/main/res/drawable-hdpi/quarter_note.png
similarity index 100%
rename from android/res/drawable-hdpi/quarter_note.png
rename to app/src/main/res/drawable-hdpi/quarter_note.png
diff --git a/android/res/drawable-hdpi/sixteenth_note.png b/app/src/main/res/drawable-hdpi/sixteenth_note.png
similarity index 100%
rename from android/res/drawable-hdpi/sixteenth_note.png
rename to app/src/main/res/drawable-hdpi/sixteenth_note.png
diff --git a/android/res/drawable-hdpi/stop.png b/app/src/main/res/drawable-hdpi/stop.png
similarity index 100%
rename from android/res/drawable-hdpi/stop.png
rename to app/src/main/res/drawable-hdpi/stop.png
diff --git a/android/res/drawable-hdpi/thirtysecond_note.png b/app/src/main/res/drawable-hdpi/thirtysecond_note.png
similarity index 100%
rename from android/res/drawable-hdpi/thirtysecond_note.png
rename to app/src/main/res/drawable-hdpi/thirtysecond_note.png
diff --git a/android/res/drawable-hdpi/trash.png b/app/src/main/res/drawable-hdpi/trash.png
similarity index 100%
rename from android/res/drawable-hdpi/trash.png
rename to app/src/main/res/drawable-hdpi/trash.png
diff --git a/android/res/drawable-hdpi/unknown_note.png b/app/src/main/res/drawable-hdpi/unknown_note.png
similarity index 100%
rename from android/res/drawable-hdpi/unknown_note.png
rename to app/src/main/res/drawable-hdpi/unknown_note.png
diff --git a/android/res/drawable-hdpi/up.png b/app/src/main/res/drawable-hdpi/up.png
similarity index 100%
rename from android/res/drawable-hdpi/up.png
rename to app/src/main/res/drawable-hdpi/up.png
diff --git a/android/res/drawable-hdpi/voice.png b/app/src/main/res/drawable-hdpi/voice.png
similarity index 100%
rename from android/res/drawable-hdpi/voice.png
rename to app/src/main/res/drawable-hdpi/voice.png
diff --git a/android/res/drawable-hdpi/whole_note.png b/app/src/main/res/drawable-hdpi/whole_note.png
similarity index 100%
rename from android/res/drawable-hdpi/whole_note.png
rename to app/src/main/res/drawable-hdpi/whole_note.png
diff --git a/android/res/drawable-hdpi/zoom.png b/app/src/main/res/drawable-hdpi/zoom.png
similarity index 100%
rename from android/res/drawable-hdpi/zoom.png
rename to app/src/main/res/drawable-hdpi/zoom.png
diff --git a/android/res/drawable-ldpi/icon.png b/app/src/main/res/drawable-ldpi/icon.png
similarity index 100%
rename from android/res/drawable-ldpi/icon.png
rename to app/src/main/res/drawable-ldpi/icon.png
diff --git a/android/res/drawable-mdpi/icon.png b/app/src/main/res/drawable-mdpi/icon.png
similarity index 100%
rename from android/res/drawable-mdpi/icon.png
rename to app/src/main/res/drawable-mdpi/icon.png
diff --git a/android/res/layout-sw600dp/piano2.xml b/app/src/main/res/layout-sw600dp/piano2.xml
similarity index 100%
rename from android/res/layout-sw600dp/piano2.xml
rename to app/src/main/res/layout-sw600dp/piano2.xml
diff --git a/android/res/layout/amplification.xml b/app/src/main/res/layout/amplification.xml
similarity index 100%
rename from android/res/layout/amplification.xml
rename to app/src/main/res/layout/amplification.xml
diff --git a/android/res/layout/chord_grid.xml b/app/src/main/res/layout/chord_grid.xml
similarity index 100%
rename from android/res/layout/chord_grid.xml
rename to app/src/main/res/layout/chord_grid.xml
diff --git a/android/res/layout/effects.xml b/app/src/main/res/layout/effects.xml
similarity index 100%
rename from android/res/layout/effects.xml
rename to app/src/main/res/layout/effects.xml
diff --git a/android/res/layout/karplus_strong.xml b/app/src/main/res/layout/karplus_strong.xml
similarity index 100%
rename from android/res/layout/karplus_strong.xml
rename to app/src/main/res/layout/karplus_strong.xml
diff --git a/android/res/layout/knobpreflayout_va.xml b/app/src/main/res/layout/knobpreflayout_va.xml
similarity index 100%
rename from android/res/layout/knobpreflayout_va.xml
rename to app/src/main/res/layout/knobpreflayout_va.xml
diff --git a/android/res/layout/knobpreflayout_vs.xml b/app/src/main/res/layout/knobpreflayout_vs.xml
similarity index 100%
rename from android/res/layout/knobpreflayout_vs.xml
rename to app/src/main/res/layout/knobpreflayout_vs.xml
diff --git a/android/res/layout/low_pass_filter.xml b/app/src/main/res/layout/low_pass_filter.xml
similarity index 100%
rename from android/res/layout/low_pass_filter.xml
rename to app/src/main/res/layout/low_pass_filter.xml
diff --git a/android/res/layout/main.xml b/app/src/main/res/layout/main.xml
similarity index 100%
rename from android/res/layout/main.xml
rename to app/src/main/res/layout/main.xml
diff --git a/android/res/layout/oscillator.xml b/app/src/main/res/layout/oscillator.xml
similarity index 100%
rename from android/res/layout/oscillator.xml
rename to app/src/main/res/layout/oscillator.xml
diff --git a/android/res/layout/piano.xml b/app/src/main/res/layout/piano.xml
similarity index 100%
rename from android/res/layout/piano.xml
rename to app/src/main/res/layout/piano.xml
diff --git a/android/res/layout/piano2.xml b/app/src/main/res/layout/piano2.xml
similarity index 100%
rename from android/res/layout/piano2.xml
rename to app/src/main/res/layout/piano2.xml
diff --git a/android/res/layout/score.xml b/app/src/main/res/layout/score.xml
similarity index 100%
rename from android/res/layout/score.xml
rename to app/src/main/res/layout/score.xml
diff --git a/android/res/layout/tremolo.xml b/app/src/main/res/layout/tremolo.xml
similarity index 100%
rename from android/res/layout/tremolo.xml
rename to app/src/main/res/layout/tremolo.xml
diff --git a/android/res/layout/vibrato.xml b/app/src/main/res/layout/vibrato.xml
similarity index 100%
rename from android/res/layout/vibrato.xml
rename to app/src/main/res/layout/vibrato.xml
diff --git a/android/res/menu/options_menu.xml b/app/src/main/res/menu/options_menu.xml
similarity index 100%
rename from android/res/menu/options_menu.xml
rename to app/src/main/res/menu/options_menu.xml
diff --git a/android/res/menu/score_menu.xml b/app/src/main/res/menu/score_menu.xml
similarity index 100%
rename from android/res/menu/score_menu.xml
rename to app/src/main/res/menu/score_menu.xml
diff --git a/android/res/menu/synth_menu.xml b/app/src/main/res/menu/synth_menu.xml
similarity index 100%
rename from android/res/menu/synth_menu.xml
rename to app/src/main/res/menu/synth_menu.xml
diff --git a/android/res/raw/presets.txt b/app/src/main/res/raw/presets.txt
similarity index 100%
rename from android/res/raw/presets.txt
rename to app/src/main/res/raw/presets.txt
diff --git a/android/res/raw/rom1a.syx b/app/src/main/res/raw/rom1a.syx
similarity index 100%
rename from android/res/raw/rom1a.syx
rename to app/src/main/res/raw/rom1a.syx
diff --git a/android/res/values-sw600dp/dimens.xml b/app/src/main/res/values-sw600dp/dimens.xml
similarity index 100%
rename from android/res/values-sw600dp/dimens.xml
rename to app/src/main/res/values-sw600dp/dimens.xml
diff --git a/android/res/values-v11/styles.xml b/app/src/main/res/values-v11/styles.xml
similarity index 100%
rename from android/res/values-v11/styles.xml
rename to app/src/main/res/values-v11/styles.xml
diff --git a/android/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
similarity index 100%
rename from android/res/values/attrs.xml
rename to app/src/main/res/values/attrs.xml
diff --git a/android/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
similarity index 100%
rename from android/res/values/dimens.xml
rename to app/src/main/res/values/dimens.xml
diff --git a/android/res/values/strings.xml b/app/src/main/res/values/strings.xml
similarity index 100%
rename from android/res/values/strings.xml
rename to app/src/main/res/values/strings.xml
diff --git a/android/res/values/styles.xml b/app/src/main/res/values/styles.xml
similarity index 100%
rename from android/res/values/styles.xml
rename to app/src/main/res/values/styles.xml
diff --git a/android/res/xml/device_filter.xml b/app/src/main/res/xml/device_filter.xml
similarity index 100%
rename from android/res/xml/device_filter.xml
rename to app/src/main/res/xml/device_filter.xml
diff --git a/android/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
similarity index 100%
rename from android/res/xml/preferences.xml
rename to app/src/main/res/xml/preferences.xml
diff --git a/app/src/test/java/com/levien/synthesizer/ExampleUnitTest.java b/app/src/test/java/com/levien/synthesizer/ExampleUnitTest.java
new file mode 100644
index 0000000..a318606
--- /dev/null
+++ b/app/src/test/java/com/levien/synthesizer/ExampleUnitTest.java
@@ -0,0 +1,15 @@
+package com.levien.synthesizer;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * To work on unit tests, switch the Test Artifact in the Build Variants view.
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..238a7c7
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,23 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle-experimental:0.7.2'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/build.xml b/build.xml
deleted file mode 100644
index c95addd..0000000
--- a/build.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/core/.gitignore b/core/.gitignore
deleted file mode 100644
index ff4fd7d..0000000
--- a/core/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-build/**
-core.jar
-bin/protoc
-lib/libprotobuf.jar
\ No newline at end of file
diff --git a/core/build.xml b/core/build.xml
deleted file mode 100644
index 777dd8d..0000000
--- a/core/build.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/core/src/com/levien/synthesizer/core/model/CachedFrequencyProvider.java b/core/src/com/levien/synthesizer/core/model/CachedFrequencyProvider.java
deleted file mode 100644
index ec8f4f3..0000000
--- a/core/src/com/levien/synthesizer/core/model/CachedFrequencyProvider.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model;
-
-/**
- * Convenient base class for any module that only wants to compute a new log frequency once at each
- * step of time.
- */
-public abstract class CachedFrequencyProvider implements FrequencyProvider {
- public CachedFrequencyProvider() {
- cachedTime_ = -1;
- }
-
- /**
- * Caching implementation of the FrequencyProvider interface.
- * @param time - current synthesis time.
- */
- final public double getLogFrequency(SynthesisTime time) {
- if (time.getAbsoluteTime() != cachedTime_) {
- cachedTime_ = time.getAbsoluteTime();
- cachedValue_ = computeLogFrequency(time);
- }
- return cachedValue_;
- }
-
- /**
- * Method for subclasses to implement to compute a new value for the given time.
- */
- protected abstract double computeLogFrequency(SynthesisTime time);
-
- private double cachedTime_;
- private double cachedValue_;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/CachedSignalProvider.java b/core/src/com/levien/synthesizer/core/model/CachedSignalProvider.java
deleted file mode 100644
index eb212d1..0000000
--- a/core/src/com/levien/synthesizer/core/model/CachedSignalProvider.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model;
-
-/**
- * Convenient base class for any module that only wants to compute a new signal value once at each
- * step of time.
- */
-public abstract class CachedSignalProvider implements SignalProvider {
- public CachedSignalProvider() {
- cachedTime_ = -1;
- }
-
- /**
- * Caching implementation of the SignalProvider interface.
- * @param time - current synthesis time.
- */
- final public double getValue(SynthesisTime time) {
- double absoluteTime = time.getAbsoluteTime();
- if (absoluteTime != cachedTime_) {
- cachedTime_ = absoluteTime;
- cachedValue_ = computeValue(time);
- }
- return cachedValue_;
- }
-
- /**
- * Method for subclasses to implement to compute a new value for the given time.
- */
- protected abstract double computeValue(SynthesisTime time);
-
- private double cachedTime_;
- private double cachedValue_;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/Envelope.java b/core/src/com/levien/synthesizer/core/model/Envelope.java
deleted file mode 100755
index a92f49a..0000000
--- a/core/src/com/levien/synthesizer/core/model/Envelope.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model;
-
-/**
- * An interface for any module that shapes a sound based on something like keyboard keys being
- * pressed and released.
- */
-public interface Envelope extends SignalProvider {
- /**
- * Called to tell the envelope that the key has been pressed.
- * @param retriggerIfOn - A (hopefully temporary) hack. Tells whether to treat this as a new
- * press if the key is already down.
- */
- public abstract void turnOn(boolean retriggerIfOn);
-
- /**
- * Called to tell the envelope the key has been released.
- */
- public abstract void turnOff();
-}
diff --git a/core/src/com/levien/synthesizer/core/model/FrequencyProvider.java b/core/src/com/levien/synthesizer/core/model/FrequencyProvider.java
deleted file mode 100644
index e2e0817..0000000
--- a/core/src/com/levien/synthesizer/core/model/FrequencyProvider.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model;
-
-/**
- * An interface for modules that produce some frequency value.
- */
-public interface FrequencyProvider {
- double getLogFrequency(SynthesisTime time);
-}
diff --git a/core/src/com/levien/synthesizer/core/model/SignalProvider.java b/core/src/com/levien/synthesizer/core/model/SignalProvider.java
deleted file mode 100644
index 41a3599..0000000
--- a/core/src/com/levien/synthesizer/core/model/SignalProvider.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model;
-
-/**
- * An interface for any module that provides a signal, typically in the range [-1, 1].
- */
-public interface SignalProvider {
- /**
- * Method for subclasses to return a value for the given time.
- */
- double getValue(SynthesisTime time);
-}
diff --git a/core/src/com/levien/synthesizer/core/model/SynthesisTime.java b/core/src/com/levien/synthesizer/core/model/SynthesisTime.java
deleted file mode 100644
index e82e17f..0000000
--- a/core/src/com/levien/synthesizer/core/model/SynthesisTime.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model;
-
-/**
- * A simple counter to keep track of the logical time in synthesis.
- */
-public class SynthesisTime {
- /**
- * Creates a new timer with a 0 time delta.
- */
- public SynthesisTime() {
- deltaTime_ = 0.0;
- absoluteTime_ = 0.0;
- }
-
- /**
- * Returns how much time will elapse next time advance() is called.
- * @return the time delta in seconds.
- */
- public double getDeltaTime() {
- return deltaTime_;
- }
-
- /**
- * Returns the absolute time that has elapsed since creation or last reset().
- * @return the time in seconds.
- */
- public double getAbsoluteTime() {
- return absoluteTime_;
- }
-
- /**
- * Sets the "sample rate" of the synthesizer, which is the inverse of the time delta.
- * @param sampleRate - samples per second (in Hz).
- */
- public void setSampleRate(double sampleRate) {
- if (sampleRate == 0.0) {
- deltaTime_ = 0.0;
- } else {
- deltaTime_ = 1.0 / sampleRate;
- }
- }
-
- /**
- * Resets the absolute time to zero.
- */
- public void reset() {
- absoluteTime_ = 0.0;
- }
-
- /**
- * Advances the absolute time by the time delta.
- */
- public void advance() {
- absoluteTime_ += deltaTime_;
- }
-
- private double deltaTime_;
- private double absoluteTime_;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/SynthesizerInput.java b/core/src/com/levien/synthesizer/core/model/SynthesizerInput.java
deleted file mode 100644
index e05a17b..0000000
--- a/core/src/com/levien/synthesizer/core/model/SynthesizerInput.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model;
-
-/**
- * SynthesizerInput provides a frequency or signal that doesn't inherently change over time.
- * It can change occasionally as the user turns a knob or whatever, but doesn't change on its own.
- */
-public class SynthesizerInput implements FrequencyProvider, SignalProvider {
- /**
- * Creates a new SynthesizerInput that will return value as both a frequency and a signal.
- */
- public SynthesizerInput(double value, double min, double max) {
- value_ = value;
- min_ = min;
- max_ = max;
- }
-
- /**
- * Returns the input value as a log of frequency.
- * @return the value.
- */
- public synchronized double getLogFrequency(SynthesisTime time) {
- return value_;
- }
-
- /**
- * Returns the input value as a signal.
- * @return the value.
- */
- public synchronized double getValue(SynthesisTime time) {
- return value_;
- }
-
- /**
- * Returns the input value.
- * @return the value.
- */
- public synchronized double getSynthesizerInputValue() {
- return value_;
- }
-
- /**
- * Sets the input to a new value.
- * @param value - the new value.
- */
- public synchronized void setValue(double value) {
- value_ = value;
- }
-
- /**
- * Sets the input based on an unsigned byte value in the range 0 to 127.
- */
- public synchronized void setByteValue(byte value) {
- value_ = min_ + (value / 127.0) * (max_ - min_);
- }
-
- private double min_;
- private double max_;
- private double value_;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/WaveformInput.java b/core/src/com/levien/synthesizer/core/model/WaveformInput.java
deleted file mode 100644
index 6065f13..0000000
--- a/core/src/com/levien/synthesizer/core/model/WaveformInput.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model;
-
-import java.util.ArrayList;
-
-/**
- * WaveformInput provides a waveform type that is selectable.
- */
-public class WaveformInput {
- /**
- * Creates a new WaveformInput with the given initial value.
- */
- public WaveformInput(String waveform) {
- selected_ = 0;
- waveforms_ = new ArrayList();
- waveforms_.add(waveform);
- }
-
- /**
- * @return the index of the given waveform.
- */
- public synchronized int getWaveformIndex(String waveform) {
- for (int i = 0; i < waveforms_.size(); ++i) {
- if (waveforms_.get(i).equals(waveform)) {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * Selects a waveform.
- */
- public synchronized void select(String waveform) {
- selected_ = getWaveformIndex(waveform);
- if (selected_ < 0) {
- selected_ = 0;
- }
- }
-
- /**
- * Select the next available waveform.
- */
- public synchronized void next() {
- selected_ = (selected_ + 1) % waveforms_.size();
- }
-
- /**
- * Select the previous available waveform.
- */
- public synchronized void previous() {
- if (selected_ == 0) {
- selected_ = waveforms_.size() - 1;
- } else {
- --selected_;
- }
- }
-
- /**
- * Returns the currently selected waveform.
- */
- public synchronized int getSelected() {
- return selected_;
- }
-
- /**
- * Adds a new waveform to this input.
- * @return The index of the new waveform.
- */
- public synchronized int addWaveform(String waveform) {
- int id = getWaveformIndex(waveform);
- if (id < 0) {
- id = waveforms_.size();
- waveforms_.add(waveform);
- }
- return id;
- }
-
- /**
- * @return The number of waveforms that are selectable.
- */
- public synchronized int getWaveformCount() {
- return waveforms_.size();
- }
-
- /**
- * @return The identifier of the waveform with the given index.
- */
- public synchronized String getWaveform(int i) {
- return waveforms_.get(i);
- }
-
- // The currently selected waveform.
- private int selected_;
-
- // The set of all available waveforms on this input.
- private ArrayList waveforms_;
-
- // A few default built-in strings.
- public static String SINE = "sine";
- public static String TRIANGLE = "triangle";
- public static String SQUARE = "square";
- public static String SAWTOOTH = "sawtooth";
- public static String NOISE = "noise";
- public static String KARPLUS_STRONG = "karplus-strong string";
- public static String DRAWBAR_ORGAN = "drawbar organ";
- public static String DRUMS = "drums";
-}
diff --git a/core/src/com/levien/synthesizer/core/model/composite/MidiSynthesizer.java b/core/src/com/levien/synthesizer/core/model/composite/MidiSynthesizer.java
deleted file mode 100644
index 3de5eda..0000000
--- a/core/src/com/levien/synthesizer/core/model/composite/MidiSynthesizer.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model.composite;
-
-import com.levien.synthesizer.core.model.SignalProvider;
-import com.levien.synthesizer.core.music.Note;
-import com.levien.synthesizer.core.soundfont.SoundFontReader;
-
-/**
- * MidiSynthesizer is a wrapper around MultiTouchSynthesizer that allows it to accept Midi input in
- * a more natural way. As more notes are played, more simulated fingers are used, until there
- * aren't any more available, in which case notes are dropped.
- */
-public class MidiSynthesizer extends MultiTouchSynthesizer implements SignalProvider {
- /**
- * Creates a new MidiSynthesizer that wraps MultiTouchSynthesizer with a given number of fingers.
- * @param fingers - How many fingers to simulate.
- * @param sampleRateInHz - The sample rate of the wrapped synthesizer.
- */
- public MidiSynthesizer(int fingers, double sampleRateInHz, SoundFontReader sampleProvider) {
- super(fingers, sampleRateInHz, sampleProvider);
- noteDown_ = new int[FINGERS];
- for (int i = 0; i < FINGERS; ++i) {
- noteDown_[i] = -1;
- }
- }
-
- /**
- * Called to handle Midi note-on events.
- * @param note - The note to turn on.
- * @param velocity - How hard the key was pressed, from 0 to 127.
- */
- public void onNoteOn(int note, int velocity) {
- if (velocity == 0) {
- onNoteOff(note, velocity);
- } else {
- for (int i = 0; i < FINGERS; ++i) {
- if (noteDown_[i] < 0) {
- noteDown_[i] = note;
- setPitch(Note.computeLog12TET(note % 12, note / 12), i);
- turnOn(true, i);
- break;
- }
- }
- }
- }
-
- /**
- * Called to handle Midi note-off events.
- * @param note - The note to turn off.
- * @param velocity - How hard the key was (un?)pressed, from 0 to 127.
- */
- public void onNoteOff(int note, int velocity) {
- for (int i = 0; i < FINGERS; ++i) {
- if (noteDown_[i] == note) {
- noteDown_[i] = -1;
- turnOff(i);
- break;
- }
- }
- }
-
- // The map of which notes are being held down by each finger.
- private int[] noteDown_;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/composite/MultiChannelSynthesizer.java b/core/src/com/levien/synthesizer/core/model/composite/MultiChannelSynthesizer.java
deleted file mode 100644
index 9e1e4c6..0000000
--- a/core/src/com/levien/synthesizer/core/model/composite/MultiChannelSynthesizer.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model.composite;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.logging.Logger;
-
-import com.google.protobuf.TextFormat;
-import com.levien.synthesizer.core.midi.MidiAdapter;
-import com.levien.synthesizer.core.model.SignalProvider;
-import com.levien.synthesizer.core.model.SynthesisTime;
-import com.levien.synthesizer.core.model.SynthesizerInput;
-import com.levien.synthesizer.core.model.composite.Presets.PresetLibrary;
-import com.levien.synthesizer.core.model.composite.Presets.Setting;
-import com.levien.synthesizer.core.soundfont.SoundFontReader;
-
-/**
- * MultiChannelSynthesizer is an array of MidiSynthesizer.
- */
-public class MultiChannelSynthesizer extends MidiAdapter implements SignalProvider {
- /**
- * MultiChannelSynthesizer is an array of BasicSynths.
- * @param channels - The number of channels of the synthesizer.
- * @param fingers - How many fingers to support.
- * @param sampleRateInHz - The sample rate of the underlying BasicSynths.
- */
- public MultiChannelSynthesizer(int channels, int fingers, double sampleRateInHz,
- SoundFontReader sampleProvider) {
- logger_ = Logger.getLogger(getClass().getName());
- synth_ = new MidiSynthesizer[channels];
- for (int i = 0; i < synth_.length; ++i) {
- synth_[i] = new MidiSynthesizer(fingers, sampleRateInHz, sampleProvider);
- }
- }
-
- /**
- * Returns the output of the synthesizer.
- */
- public double getValue(SynthesisTime time) {
- double value = 0.0;
- for (int i = 0; i < synth_.length; ++i) {
- value += synth_[i].getValue(time);
- }
- return value;
- }
-
- /**
- * Called to turn on the given note for the given channel.
- */
- @Override
- public void onNoteOn(int channel, int note, int velocity) {
- synth_[channel].onNoteOn(note, velocity);
- }
-
- /**
- * Called to turn off the given note for the given channel.
- */
- @Override
- public void onNoteOff(int channel, int note, int velocity) {
- synth_[channel].onNoteOff(note, velocity);
- }
-
- /**
- * Called when a control value changes on the given channel.
- */
- @Override
- public void onController(int channel, int control, int value) {
- MidiSynthesizer synth = synth_[channel];
- Setting setting = Setting.valueOf(control);
- SynthesizerInput input = synth.getSynthesizerInput(setting);
- if (input != null) {
- input.setByteValue((byte)value);
- logger_.warning(
- "Processed control: " + setting.name() + "[" + channel + "] = " + value + ".");
- } else {
- logger_.warning("Unhandled control: " + control + "[" + channel + "] = " + value + ".");
- }
- }
-
- /**
- * Called when the program is changed.
- */
- @Override
- public void onProgramChange(int channel, int program) {
- synth_[channel].setPreset(program);
- }
-
- /**
- * Populates names with the list of all known presets from the library.
- * Does *not* clear the list first.
- */
- public void getPresetNames(ArrayList names) {
- synth_[0].getPresetNames(names);
- }
-
- /**
- * Populates library with the presets from the given input stream, in text protocol buffer format.
- */
- public void loadLibraryFromText(InputStream input) throws IOException {
- PresetLibrary.Builder builder = PresetLibrary.newBuilder();
- TextFormat.merge(new InputStreamReader(input), builder);
- PresetLibrary library = builder.build();
- for (int i = 0; i < synth_.length; ++i) {
- synth_[i].setLibrary(library);
- // Load each channel with the next available preset.
- synth_[i].setPreset(i % synth_[i].getPresetCount());
- }
- }
-
- /**
- * Loads a channel with the settings from the preset in the library with the given index.
- */
- public void setPreset(int channel, int index) {
- synth_[channel].setPreset(index);
- }
-
- /**
- * Returns the MidiSynthesizer to use for a particular channel.
- */
- public MidiSynthesizer getChannel(int channel) {
- return synth_[channel];
- }
-
- // The actual synthesizers.
- private MidiSynthesizer[] synth_;
-
- Logger logger_;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/composite/MultiTouchSynthesizer.java b/core/src/com/levien/synthesizer/core/model/composite/MultiTouchSynthesizer.java
deleted file mode 100644
index 06a69b7..0000000
--- a/core/src/com/levien/synthesizer/core/model/composite/MultiTouchSynthesizer.java
+++ /dev/null
@@ -1,638 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model.composite;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import com.levien.synthesizer.core.model.CachedSignalProvider;
-import com.levien.synthesizer.core.model.Envelope;
-import com.levien.synthesizer.core.model.FrequencyProvider;
-import com.levien.synthesizer.core.model.SignalProvider;
-import com.levien.synthesizer.core.model.SynthesisTime;
-import com.levien.synthesizer.core.model.SynthesizerInput;
-import com.levien.synthesizer.core.model.WaveformInput;
-import com.levien.synthesizer.core.model.composite.Presets.Preset;
-import com.levien.synthesizer.core.model.composite.Presets.PresetLibrary;
-import com.levien.synthesizer.core.model.composite.Presets.Setting;
-import com.levien.synthesizer.core.model.modules.AdsrEnvelope;
-import com.levien.synthesizer.core.model.modules.Amplifier;
-import com.levien.synthesizer.core.model.modules.Delay;
-import com.levien.synthesizer.core.model.modules.Echo;
-import com.levien.synthesizer.core.model.modules.Glide;
-import com.levien.synthesizer.core.model.modules.LowPassFilter;
-import com.levien.synthesizer.core.model.modules.Mixer;
-import com.levien.synthesizer.core.model.modules.Tremolo;
-import com.levien.synthesizer.core.model.modules.Tuner;
-import com.levien.synthesizer.core.model.modules.WaveformSelector;
-import com.levien.synthesizer.core.model.oscillator.DrawbarOrgan;
-import com.levien.synthesizer.core.model.oscillator.KarplusStrong;
-import com.levien.synthesizer.core.soundfont.SoundFontOscillator;
-import com.levien.synthesizer.core.soundfont.SoundFontReader;
-
-/**
- * MultiTouchSynthesizer is a collection of synthesizer modules, connected together in a way similar
- * to many basic analog synthesizers.
- */
-public class MultiTouchSynthesizer implements SignalProvider {
- /**
- * Creates a new synthesizer with default settings.
- * @param sampleRateInHz - Sample rate, used to compute buffer size from delay time.
- */
- public MultiTouchSynthesizer(int fingers, double sampleRateInHz, SoundFontReader sampleLibrary) {
- FINGERS = fingers;
- setup(sampleRateInHz, sampleLibrary);
- }
-
- /**
- * Connects all of the modules together.
- * @param sampleRateInHz - Sample rate, used to compute buffer size from delay time.
- */
- @SuppressWarnings("unchecked")
- private void setup(double sampleRateInHz, SoundFontReader sampleLibrary) {
- // Data Structures.
- library_ = PresetLibrary.newBuilder().build();
- pitch_ = new SynthesizerInput[FINGERS];
- synthesizerInputs_ = new HashMap();
- waveformInputs_ = new HashMap();
- envelopes_ = new ArrayList[FINGERS];
- for (int i = 0; i < FINGERS; ++i) {
- pitch_[i] = new SynthesizerInput(0.0, 4.0, 15.0);
- envelopes_[i] = new ArrayList();
- }
-
- // Vibrato
- SignalProvider[] vibrato = setupVibrato();
-
- // Oscillator 1
- SignalProvider[] oscillator1 = setupOscillator(Setting.OSCILLATOR_1_GLIDE,
- Setting.OSCILLATOR_1_COARSE,
- Setting.OSCILLATOR_1_FINE,
- Setting.OSCILLATOR_1_VIBRATO,
- Setting.OSCILLATOR_1_WAVEFORM,
- Setting.OSCILLATOR_1_BLEND,
- Setting.OSCILLATOR_1_STRETCH,
- Setting.OSCILLATOR_1_EXCITEMENT,
- pitch_,
- vibrato,
- true,
- sampleLibrary,
- sampleRateInHz);
- // Oscillator 2
- SignalProvider[] oscillator2 = setupOscillator(Setting.OSCILLATOR_2_GLIDE,
- Setting.OSCILLATOR_2_COARSE,
- Setting.OSCILLATOR_2_FINE,
- Setting.OSCILLATOR_2_VIBRATO,
- Setting.OSCILLATOR_2_WAVEFORM,
- Setting.OSCILLATOR_2_BLEND,
- Setting.OSCILLATOR_2_STRETCH,
- Setting.OSCILLATOR_2_EXCITEMENT,
- pitch_,
- vibrato,
- true,
- sampleLibrary,
- sampleRateInHz);
-
- // Mixing
- SynthesizerInput balance = new SynthesizerInput(0.0, 0.0, 1.0);
- synthesizerInputs_.put(Setting.BALANCE, balance);
- SignalProvider[] oscillatorOutput = new SignalProvider[FINGERS];
- for (int finger = 0; finger < FINGERS; ++finger) {
- oscillatorOutput[finger] = new Mixer(oscillator1[finger], oscillator2[finger], balance);
- }
-
- // Tremolo
- SignalProvider[] tremolo = setupTremolo(oscillatorOutput);
-
- // Low-pass Filter
- SignalProvider[] low_pass_filter = setupLowPassFilter(tremolo);
-
- // Amplifier
- SignalProvider[] envelope = setupEnvelope(Setting.ATTACK,
- Setting.DECAY,
- Setting.SUSTAIN,
- Setting.RELEASE);
- SynthesizerInput volume = new SynthesizerInput(1.0, 0.0, 25.0);
- synthesizerInputs_.put(Setting.VOLUME, volume);
-
- final SignalProvider[] ampOutput = new SignalProvider[FINGERS];
- for (int finger = 0; finger < FINGERS; ++finger) {
- SignalProvider amplification = new Amplifier(envelope[finger], volume);
- ampOutput[finger] = new Amplifier(low_pass_filter[finger], amplification);
- }
-
- // Merge the fingers.
- SignalProvider mergedOutput = new SignalProvider() {
- public double getValue(SynthesisTime time) {
- double output = 0.0;
- for (int finger = 0; finger < FINGERS; ++finger) {
- output += ((1.0 / FINGERS) * ampOutput[finger].getValue(time));
- }
- return output;
- }
- };
-
- // Effects
- SignalProvider echo = setupEcho(mergedOutput, sampleRateInHz);
- output_ = setupDelay(echo);
- }
-
- /**
- * Sets up an envelope.
- */
- private SignalProvider[] setupEnvelope(Setting attackSetting,
- Setting decaySetting,
- Setting sustainSetting,
- Setting releaseSetting) {
- SynthesizerInput attack = new SynthesizerInput(0.01, 0.01, 1.0);
- SynthesizerInput decay = new SynthesizerInput(0.01, 0.01, 1.0);
- SynthesizerInput sustain = new SynthesizerInput(1.0, 0.0, 1.0);
- SynthesizerInput release = new SynthesizerInput(0.01, 0.01, 1.0);
-
- synthesizerInputs_.put(attackSetting, attack);
- synthesizerInputs_.put(decaySetting, decay);
- synthesizerInputs_.put(sustainSetting, sustain);
- synthesizerInputs_.put(releaseSetting, release);
-
- SignalProvider[] response = new SignalProvider[FINGERS];
- for (int finger = 0; finger < FINGERS; ++finger) {
- Envelope envelope = new AdsrEnvelope(attack, decay, sustain, release);
- envelopes_[finger].add(envelope);
- response[finger] = envelope;
- }
- return response;
- }
-
- /**
- * Sets up the vibrato section of the synthesizer.
- */
- private SignalProvider[] setupVibrato() {
- SynthesizerInput rate = new SynthesizerInput(0.0, 0.0, 10.0);
- WaveformInput waveform = new WaveformInput(WaveformInput.SINE);
- synthesizerInputs_.put(Setting.VIBRATO_RATE, rate);
- waveformInputs_.put(Setting.VIBRATO_WAVEFORM, waveform);
- SignalProvider[] envelope = setupEnvelope(Setting.VIBRATO_ATTACK,
- Setting.VIBRATO_DECAY,
- Setting.VIBRATO_SUSTAIN,
- Setting.VIBRATO_RELEASE);
- SignalProvider[] response = new SignalProvider[FINGERS];
- for (int finger = 0; finger < FINGERS; ++finger) {
- WaveformSelector waveformOutput = new WaveformSelector(waveform);
- waveformOutput.addDefaultWaveforms(rate);
- response[finger] = new Amplifier(waveformOutput, envelope[finger]);
- }
- return response;
- }
-
- /**
- * Sets up a Karplus-Strong string section of the synthesizer.
- */
- private SignalProvider[] setupKarplusStrong(Setting blendSetting,
- Setting stretchSetting,
- Setting excitementSetting,
- FrequencyProvider[] pitch,
- double sampleRateInHz) {
- SynthesizerInput blend = new SynthesizerInput(0.0, 0.0, 1.0);
- SynthesizerInput stretch = new SynthesizerInput(0.0, 0.0, 1.0);
- SynthesizerInput excitement = new SynthesizerInput(0.0, 0.0, 1.0);
-
- synthesizerInputs_.put(blendSetting, blend);
- synthesizerInputs_.put(stretchSetting, stretch);
- synthesizerInputs_.put(excitementSetting, excitement);
-
- SignalProvider[] response = new SignalProvider[FINGERS];
- for (int finger = 0; finger < FINGERS; ++finger) {
- KarplusStrong karplusStrong =
- new KarplusStrong(pitch[finger], blend, stretch, excitement, sampleRateInHz);
- envelopes_[finger].add(karplusStrong);
- response[finger] = karplusStrong;
- }
- return response;
- }
-
- /**
- * Sets up a drawbar organ osciallator for each finger.
- */
- private SignalProvider[] setupDrawbarOrgan(FrequencyProvider[] pitch) {
- SynthesizerInput drawbar1 = new SynthesizerInput(8.0/8.0, 0.0, 1.0);
- SynthesizerInput drawbar2 = new SynthesizerInput(8.0/8.0, 0.0, 1.0);
- SynthesizerInput drawbar3 = new SynthesizerInput(8.0/8.0, 0.0, 1.0);
- SynthesizerInput drawbar4 = new SynthesizerInput(8.0/8.0, 0.0, 1.0);
- SynthesizerInput drawbar5 = new SynthesizerInput(0.0/8.0, 0.0, 1.0);
- SynthesizerInput drawbar6 = new SynthesizerInput(0.0/8.0, 0.0, 1.0);
- SynthesizerInput drawbar7 = new SynthesizerInput(0.0/8.0, 0.0, 1.0);
- SynthesizerInput drawbar8 = new SynthesizerInput(0.0/8.0, 0.0, 1.0);
- SynthesizerInput drawbar9 = new SynthesizerInput(0.0/8.0, 0.0, 1.0);
- synthesizerInputs_.put(Setting.ORGAN_DRAWBAR_1, drawbar1);
- synthesizerInputs_.put(Setting.ORGAN_DRAWBAR_2, drawbar2);
- synthesizerInputs_.put(Setting.ORGAN_DRAWBAR_3, drawbar3);
- synthesizerInputs_.put(Setting.ORGAN_DRAWBAR_4, drawbar4);
- synthesizerInputs_.put(Setting.ORGAN_DRAWBAR_5, drawbar5);
- synthesizerInputs_.put(Setting.ORGAN_DRAWBAR_6, drawbar6);
- synthesizerInputs_.put(Setting.ORGAN_DRAWBAR_7, drawbar7);
- synthesizerInputs_.put(Setting.ORGAN_DRAWBAR_8, drawbar8);
- synthesizerInputs_.put(Setting.ORGAN_DRAWBAR_9, drawbar9);
- SignalProvider[] response = new SignalProvider[FINGERS];
- for (int finger = 0; finger < FINGERS; ++finger) {
- DrawbarOrgan organ = new DrawbarOrgan(pitch[finger],
- drawbar1,
- drawbar2,
- drawbar3,
- drawbar4,
- drawbar5,
- drawbar6,
- drawbar7,
- drawbar8,
- drawbar9);
- response[finger] = organ;
- }
- return response;
- }
-
- /**
- * Sets up a sampled drum.
- */
- private SignalProvider[] setupDrums(FrequencyProvider[] pitch,
- double sampleRateInHz,
- SoundFontReader sampleLibrary) {
- SignalProvider[] response = new SignalProvider[FINGERS];
- for (int finger = 0; finger < FINGERS; ++finger) {
- SoundFontOscillator sample = new SoundFontOscillator(
- pitch[finger],
- sampleLibrary.getPresets().get(sampleLibrary.getPresets().size() - 1),
- sampleRateInHz);
- response[finger] = sample;
- envelopes_[finger].add(sample);
- }
- return response;
- }
-
- /**
- * Sets up an oscillator section of the synthesizer.
- */
- private SignalProvider[] setupOscillator(Setting glideSetting,
- Setting coarseSetting,
- Setting fineSetting,
- Setting vibratoSetting,
- Setting waveformSetting,
- Setting blendSetting,
- Setting stretchSetting,
- Setting excitementSetting,
- FrequencyProvider[] pitch,
- SignalProvider[] vibrato,
- boolean includeOrgan,
- SoundFontReader sampleLibrary,
- double sampleRateInHz) {
- SynthesizerInput glide = new SynthesizerInput(0.0, 0.0, 1.0);
- SynthesizerInput coarse = new SynthesizerInput(0.0, -1.0, 1.0);
- SynthesizerInput fine = new SynthesizerInput(0.0, -0.0833333333, 0.0833333333);
- SynthesizerInput vibratoDepth = new SynthesizerInput(0.0, 0.0, 0.1666666667);
- WaveformInput waveform = new WaveformInput(WaveformInput.SINE);
-
- // Register all of the inputs.
- synthesizerInputs_.put(glideSetting, glide);
- synthesizerInputs_.put(coarseSetting, coarse);
- synthesizerInputs_.put(fineSetting, fine);
- synthesizerInputs_.put(vibratoSetting, vibratoDepth);
- waveformInputs_.put(waveformSetting, waveform);
-
- // Create a KarplusStrong module.
- SignalProvider[] karplusStrong =
- setupKarplusStrong(blendSetting, stretchSetting, excitementSetting, pitch, sampleRateInHz);
-
- // Create an organ module.
- SignalProvider[] organ = null;
- if (includeOrgan) {
- organ = setupDrawbarOrgan(pitch);
- }
-
- // Create a drum module.
- SignalProvider[] drums = null;
- if (sampleLibrary != null) {
- drums = setupDrums(pitch, sampleRateInHz, sampleLibrary);
- }
-
- SignalProvider[] response = new SignalProvider[FINGERS];
- for (int finger = 0; finger < FINGERS; ++finger) {
- // Apply all of the layers that can control pitch;
- FrequencyProvider adjustedPitch = new Glide(pitch[finger], glide);
- adjustedPitch = new Tuner(adjustedPitch, coarse);
- adjustedPitch = new Tuner(adjustedPitch, fine);
- adjustedPitch = new Tuner(adjustedPitch, new Amplifier(vibrato[finger], vibratoDepth));
-
- // Create the waveform.
- WaveformSelector selector = new WaveformSelector(waveform);
- selector.addDefaultWaveforms(adjustedPitch);
- selector.addWaveform(WaveformInput.KARPLUS_STRONG, karplusStrong[finger]);
- if (organ != null) {
- selector.addWaveform(WaveformInput.DRAWBAR_ORGAN, organ[finger]);
- }
- if (drums != null) {
- selector.addWaveform(WaveformInput.DRUMS, drums[finger]);
- }
- response[finger] = selector;
- }
- return response;
- }
-
- /**
- * Sets up the tremolo section of the synthesizer.
- */
- private SignalProvider[] setupTremolo(SignalProvider[] source) {
- SynthesizerInput rate = new SynthesizerInput(0.0, 0.0, 10.0);
- SynthesizerInput depth = new SynthesizerInput(0.0, 0.0, 1.0);
- WaveformInput waveform = new WaveformInput(WaveformInput.SINE);
-
- synthesizerInputs_.put(Setting.TREMOLO_RATE, rate);
- synthesizerInputs_.put(Setting.TREMOLO_DEPTH, depth);
- waveformInputs_.put(Setting.TREMOLO_WAVEFORM, waveform);
-
- SignalProvider[] envelope = setupEnvelope(Setting.TREMOLO_ATTACK,
- Setting.TREMOLO_DECAY,
- Setting.TREMOLO_SUSTAIN,
- Setting.TREMOLO_RELEASE);
-
- SignalProvider[] response = new SignalProvider[FINGERS];
- for (int finger = 0; finger < FINGERS; ++finger) {
- WaveformSelector waveformOutput = new WaveformSelector(waveform);
- waveformOutput.addDefaultWaveforms(rate);
- response[finger] =
- new Amplifier(source[finger],
- new Tremolo(new Amplifier(waveformOutput, envelope[finger]), depth));
- }
- return response;
- }
-
- /**
- * Sets up the filter section of the synthesizer.
- */
- private SignalProvider[] setupLowPassFilter(SignalProvider[] source) {
- final SynthesizerInput cutoff = new SynthesizerInput(1.0, 0.0, 1.0);
- final SynthesizerInput depth = new SynthesizerInput(0.0, -1.0, 1.0);
-
- synthesizerInputs_.put(Setting.FILTER_CUTOFF, cutoff);
- synthesizerInputs_.put(Setting.FILTER_DEPTH, depth);
-
- final SignalProvider[] envelope = setupEnvelope(Setting.FILTER_ATTACK,
- Setting.FILTER_DECAY,
- Setting.FILTER_SUSTAIN,
- Setting.FILTER_RELEASE);
-
- SignalProvider[] response = new SignalProvider[FINGERS];
- for (int finger = 0; finger < FINGERS; ++finger) {
- final SignalProvider envelope_finger = envelope[finger];
-
- SignalProvider shapedCutoff = new CachedSignalProvider() {
- public synchronized double computeValue(SynthesisTime time) {
- double c = cutoff.getValue(time);
- double d = depth.getValue(time);
- // This fancy math makes the envelope behave like we want.
- double x = c * Math.abs(d) - 0.5 * (d + Math.abs(d));
- return c + x * (envelope_finger.getValue(time) - 1);
- }
- };
- response[finger] = new LowPassFilter(source[finger], shapedCutoff);
- }
- return response;
- }
-
- /**
- * Sets up an echo module on the synthesizer.
- */
- private SignalProvider setupEcho(SignalProvider source, double sampleRateInHz) {
- SynthesizerInput mix = new SynthesizerInput(0.0, 0.0, 1.0);
- SynthesizerInput delay = new SynthesizerInput(0.0, 0.1, 2.0);
-
- synthesizerInputs_.put(Setting.ECHO_MIX, mix);
- synthesizerInputs_.put(Setting.ECHO_DELAY, delay);
-
- return new Echo(source, mix, delay, sampleRateInHz);
- }
-
- /**
- * Sets up the delay module for the synthesizer.
- */
- private SignalProvider setupDelay(SignalProvider source) {
- SynthesizerInput mix = new SynthesizerInput(0.5, 0.0, 1.0);
- synthesizerInputs_.put(Setting.DELAY_MIX, mix);
- delay_ = new Delay(source, mix);
- return delay_;
- }
-
- /**
- * Gets a particular input for this synthesizer by its control id.
- */
- public SynthesizerInput getSynthesizerInput(Setting setting) {
- if (synthesizerInputs_.containsKey(setting)) {
- return synthesizerInputs_.get(setting);
- }
- return null;
- }
-
- /**
- * Gets a particular input for this synthesizer by its control id.
- */
- public WaveformInput getWaveformInput(Setting setting) {
- if (waveformInputs_.containsKey(setting)) {
- return waveformInputs_.get(setting);
- }
- return null;
- }
-
- /**
- * Sets the input pitch of the synthesizer.
- * @param logFrequency - The log frequency of the pitch.
- */
- public void setPitch(double logFrequency, int finger) {
- if (finger < FINGERS) {
- pitch_[finger].setValue(logFrequency);
- }
- }
-
- /**
- * Returns the output of the synthesizer, as it should go to the speaker.
- */
- public double getValue(SynthesisTime time) {
- return output_.getValue(time);
- }
-
- /**
- * Turns on all envelopes used by the synth.
- * @param retriggerIfOn - A (hopefully temporary) hack. Tells whether to treat this as a new
- * press if the key is already down.
- */
- public void turnOn(boolean retriggerIfOn, int finger) {
- if (finger < FINGERS) {
- for (int i = 0; i < envelopes_[finger].size(); ++i) {
- envelopes_[finger].get(i).turnOn(retriggerIfOn);
- }
- }
- }
-
- /**
- * Turns off all envelopes used by the synth.
- */
- public void turnOff(int finger) {
- if (finger < FINGERS) {
- for (int i = 0; i < envelopes_[finger].size(); ++i) {
- envelopes_[finger].get(i).turnOff();
- }
- }
- }
-
- /**
- * Starts recording what the user plays.
- */
- public void startRecording() {
- delay_.startRecording();
- }
-
- /**
- * Stops recording.
- */
- public void stopRecording() {
- delay_.stopRecording();
- }
-
- /**
- * Starts playing what the user has recorded.
- */
- public void startPlaying() {
- delay_.startPlaying();
- }
-
- /**
- * Stops playing the recorded audio.
- */
- public void stopPlaying() {
- delay_.stopPlaying();
- }
-
- /**
- * Returns whether the user's recording is being played.
- */
- public boolean isPlaying() {
- return delay_.isPlaying();
- }
-
- /**
- * Returns whether the user's playing is being recorded.
- */
- public boolean isRecording() {
- return delay_.isRecording();
- }
-
- /**
- * Loads this synthesizer with the settings from the given preset.
- */
- public void setPreset(Preset preset) {
- for (int i = 0; i < preset.getInputSettingCount(); ++i) {
- SynthesizerInput input = getSynthesizerInput(preset.getInputSetting(i).getSetting());
- if (input != null) {
- input.setValue(preset.getInputSetting(i).getValue());
- } else {
- throw new RuntimeException(
- "Unable to set synthesizer input " + preset.getInputSetting(i).getSetting());
- }
- }
- for (int i = 0; i < preset.getWaveformSettingCount(); ++i) {
- WaveformInput input = getWaveformInput(preset.getWaveformSetting(i).getSetting());
- if (input != null) {
- input.select(preset.getWaveformSetting(i).getWaveform());
- } else {
- throw new RuntimeException(
- "Unable to set synthesizer input " + preset.getWaveformSetting(i).getSetting() + ".");
- }
- }
- }
-
- /**
- * Loads this synthesizer with the settings from the preset in the library with the given name.
- */
- public void setPreset(String name) {
- for (int i = 0; i < library_.getPresetCount(); ++i) {
- if (library_.getPreset(i).getName().equals(name)) {
- setPreset(library_.getPreset(i));
- return;
- }
- }
- throw new RuntimeException("Tried to load an unknown preset: \"" + name + "\".");
- }
-
- /**
- * Loads this synthesizer with the settings from the preset in the library with the given index.
- */
- public void setPreset(int index) {
- if (index < 0 || index >= library_.getPresetCount()) {
- throw new RuntimeException("Tried to load an unknown preset: " + index + ".");
- }
- setPreset(library_.getPreset(index));
- }
-
- /**
- * Returns the number of presets available in the library.
- */
- public int getPresetCount() {
- return library_.getPresetCount();
- }
-
- /**
- * Populates names with the list of all known presets from the library.
- * Does *not* clear the list first.
- */
- public void getPresetNames(ArrayList names) {
- for (int i = 0; i < library_.getPresetCount(); ++i) {
- names.add(library_.getPreset(i).getName());
- }
- }
-
- public void setLibrary(PresetLibrary library) throws IOException {
- library_ = library;
- }
-
- /**
- * Return the maximum number of fingers that can be used.
- */
- public int getMaxFingerCount() {
- return FINGERS;
- }
-
- // Data structures for keeping track of input.
- private Map synthesizerInputs_;
- private Map waveformInputs_;
-
- // How many fingers this synthesizer supports.
- protected final int FINGERS;
-
- // Keyboard input.
- private SynthesizerInput[] pitch_;
-
- // List of envelopes that needs to be triggered when a key is pressed.
- private List[] envelopes_;
-
- //The delay module that handles recording and playback.
- private Delay delay_;
-
- //Synthesizer output.
- private SignalProvider output_;
-
- // A collection of setting presets.
- private PresetLibrary library_;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/composite/Presets.proto b/core/src/com/levien/synthesizer/core/model/composite/Presets.proto
deleted file mode 100644
index 8eb42c7..0000000
--- a/core/src/com/levien/synthesizer/core/model/composite/Presets.proto
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package synthesizer_core_proto;
-
-option java_package = "com.levien.synthesizer.core.model.composite";
-
-enum WaveformDeprecated {
- SINE = 0;
- TRIANGLE = 1;
- SQUARE = 2;
- SAWTOOTH = 3;
- NOISE = 4;
- KARPLUS_STRONG = 5;
- DRAWBAR_ORGAN = 6;
- DRUMS = 7;
- WAVEFORM_COUNT = 8;
-}
-
-enum Setting {
- TREMOLO_ATTACK = 3;
- TREMOLO_DECAY = 4;
- TREMOLO_SUSTAIN = 5;
- TREMOLO_RELEASE = 6;
- BALANCE = 9;
- ECHO_DELAY = 12;
- DELAY_MIX = 13;
- VOLUME = 14;
- VIBRATO_ATTACK = 15;
- VIBRATO_DECAY = 16;
- VIBRATO_SUSTAIN = 17;
- VIBRATO_RELEASE = 18;
- OSCILLATOR_2_COARSE = 19;
- OSCILLATOR_2_FINE = 20;
- OSCILLATOR_1_WAVEFORM_NEXT = 23;
- OSCILLATOR_2_WAVEFORM_NEXT = 24;
- TREMOLO_WAVEFORM_NEXT = 25;
- VIBRATO_WAVEFORM_NEXT = 26;
- OSCILLATOR_1_WAVEFORM = 27;
- OSCILLATOR_2_WAVEFORM = 28;
- TREMOLO_WAVEFORM = 29;
- VIBRATO_WAVEFORM = 30;
- OSCILLATOR_1_WAVEFORM_PREVIOUS = 33;
- OSCILLATOR_2_WAVEFORM_PREVIOUS = 34;
- TREMOLO_WAVEFORM_PREVIOUS = 35;
- VIBRATO_WAVEFORM_PREVIOUS = 36;
- ORGAN_DRAWBAR_1 = 42;
- ORGAN_DRAWBAR_2 = 43;
- ORGAN_DRAWBAR_3 = 50;
- ORGAN_DRAWBAR_4 = 51;
- ORGAN_DRAWBAR_5 = 52;
- ORGAN_DRAWBAR_6 = 53;
- ORGAN_DRAWBAR_7 = 54;
- ORGAN_DRAWBAR_8 = 55;
- ORGAN_DRAWBAR_9 = 56;
- OSCILLATOR_1_GLIDE = 57;
- OSCILLATOR_1_STRETCH = 58;
- OSCILLATOR_1_BLEND = 59;
- OSCILLATOR_1_EXCITEMENT = 60;
- OSCILLATOR_2_GLIDE = 61;
- OSCILLATOR_2_STRETCH = 62;
- OSCILLATOR_2_BLEND = 63;
- OSCILLATOR_2_EXCITEMENT = 65;
- FILTER_CUTOFF = 74;
- OSCILLATOR_1_COARSE = 78;
- OSCILLATOR_1_FINE = 79;
- ECHO_MIX = 94;
- FILTER_ATTACK = 105;
- FILTER_DECAY = 106;
- FILTER_SUSTAIN = 107;
- FILTER_RELEASE = 108;
- FILTER_DEPTH = 109;
- ATTACK = 110;
- DECAY = 111;
- SUSTAIN = 112;
- RELEASE = 113;
- VIBRATO_RATE = 114;
- OSCILLATOR_1_VIBRATO = 115;
- OSCILLATOR_2_VIBRATO = 116;
- TREMOLO_RATE = 117;
- TREMOLO_DEPTH = 118;
-}
-
-message InputSetting {
- optional Setting setting = 1;
- optional double value = 2;
-}
-
-message WaveformSetting {
- optional Setting setting = 1;
- optional string waveform = 2;
-}
-
-message Preset {
- optional string name = 1;
- repeated InputSetting input_setting = 2;
- repeated WaveformSetting waveform_setting = 3;
-}
-
-message PresetLibrary {
- repeated Preset preset = 1;
-}
\ No newline at end of file
diff --git a/core/src/com/levien/synthesizer/core/model/modules/AdsrEnvelope.java b/core/src/com/levien/synthesizer/core/model/modules/AdsrEnvelope.java
deleted file mode 100644
index 0ae03fb..0000000
--- a/core/src/com/levien/synthesizer/core/model/modules/AdsrEnvelope.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model.modules;
-
-import com.levien.synthesizer.core.model.CachedSignalProvider;
-import com.levien.synthesizer.core.model.Envelope;
-import com.levien.synthesizer.core.model.SignalProvider;
-import com.levien.synthesizer.core.model.SynthesisTime;
-
-/**
- * An ADSR is the most common envelope for a synth.
- */
-public class AdsrEnvelope extends CachedSignalProvider implements Envelope {
- /**
- * Creates an ADSR with the given parameters.
- * @param attack - attack time in seconds.
- * @param decay - decay time in seconds.
- * @param sustain - sustain level from 0 to 1.
- * @param release - release time in seconds.
- */
- public AdsrEnvelope(SignalProvider attack,
- SignalProvider decay,
- SignalProvider sustain,
- SignalProvider release) {
- value_ = 0.0;
- attacking_ = false;
-
- trigger_ = false;
- gate_ = false;
-
- attack_ = attack;
- decay_ = decay;
- sustain_ = sustain;
- release_ = release;
- }
-
- public synchronized double computeValue(SynthesisTime time) {
- if (trigger_) {
- attacking_ = true;
- trigger_ = false;
- // It doesn't really matter if the attack is on the leading or trailing edge of the trigger.
- // By having it start on the trailing edge for 0 and the leading edge otherwise, it makes the
- // math a tiny bit simpler and makes this a little easier to unit test.
- if (value_ == 0) {
- return value_;
- }
- }
-
- if (gate_) {
- double sustain = sustain_.getValue(time);
- if (attacking_) {
- // Attacking.
- double attack = attack_.getValue(time);
- if (attack > 0.0) {
- double timeDelta = time.getDeltaTime();
- value_ += timeDelta / attack;
- if (value_ >= 1.0) {
- // TODO(klimt): This isn't exactly right. We should really figure out what time it
- // would've reached zero, and go ahead and apply the decay for that extra time that
- // has passed.
- value_ = 1.0;
- attacking_ = false;
- }
- } else {
- value_ = 1.0;
- attacking_ = false;
- }
- } else if (value_ > sustain) {
- // Decaying.
- double decay = decay_.getValue(time);
- if (decay > 0.0) {
- double timeDelta = time.getDeltaTime();
- value_ += timeDelta * ((sustain - 1.0) / decay);
- if (value_ < sustain) {
- value_ = sustain;
- }
- } else {
- value_ = sustain;
- }
- } else if (value_ < sustain) {
- // Decaying backwards.
- // This shouldn't _normally_ happen, but can if you change the parameters over time.
- double decay = decay_.getValue(time);
- if (decay > 0.0) {
- double timeDelta = time.getDeltaTime();
- value_ -= timeDelta * ((sustain - 1.0) / decay);
- if (value_ > sustain) {
- value_ = sustain;
- }
- } else {
- value_ = sustain;
- }
- }
- } else {
- // Releasing.
- if (value_ > 0.0) {
- double release = release_.getValue(time);
- if (release > 0.0) {
- double sustain = sustain_.getValue(time);
- if (sustain == 0.0) {
- double decay = decay_.getValue(time);
- if (decay == 0.0) {
- value_ = 0.0;
- } else {
- double timeDelta = time.getDeltaTime();
- value_ -= timeDelta * ((sustain - 1.0) / decay);
- }
- } else {
- double timeDelta = time.getDeltaTime();
- value_ -= timeDelta * (sustain / release);
- }
- if (value_ < 0.0) {
- value_ = 0.0;
- }
- } else {
- value_ = 0.0;
- }
- }
- }
- return value_;
- }
-
- public synchronized void turnOn(boolean retriggerIfOn) {
- if (gate_ && !retriggerIfOn) {
- return;
- }
- trigger_ = true;
- gate_ = true;
- }
-
- public synchronized void turnOff() {
- gate_ = false;
- }
-
- /**
- * Returns whether the envelope is currently being triggered.
- */
- public synchronized boolean getTrigger() {
- return trigger_;
- }
-
- /**
- * Returns whether the key for this envelope is currently being held down.
- */
- public synchronized boolean getGate() {
- return gate_;
- }
-
- // The most recently output value from this envelope.
- private double value_;
-
- // Are we in the attack phase?
- private boolean attacking_;
-
- // Whether the envelope is "on".
- private boolean trigger_;
- private boolean gate_;
-
- // The envelope shape parameters.
- private SignalProvider attack_;
- private SignalProvider decay_;
- private SignalProvider sustain_;
- private SignalProvider release_;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/modules/Amplifier.java b/core/src/com/levien/synthesizer/core/model/modules/Amplifier.java
deleted file mode 100755
index 8dbe4ea..0000000
--- a/core/src/com/levien/synthesizer/core/model/modules/Amplifier.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model.modules;
-
-import com.levien.synthesizer.core.model.SignalProvider;
-import com.levien.synthesizer.core.model.SynthesisTime;
-
-/**
- * Amplifier simply multiplies the input signal by the input gain.
- */
-public class Amplifier implements SignalProvider {
- /**
- * Creates a new Amplifier with the given signal and gain.
- * @param inputSignal - Any input signal.
- * @param gain - The signal it's multiplied times.
- */
- public Amplifier(SignalProvider inputSignal, SignalProvider gain) {
- inputSignal_ = inputSignal;
- gain_ = gain;
- }
-
- /**
- * Returns signal * gain.
- */
- public double getValue(SynthesisTime time) {
- // Most of the time, the gain will be 0.0 because of some envelope. So this is an optimization.
- double gain = gain_.getValue(time);
- if (gain == 0.0) {
- return 0.0;
- }
- return inputSignal_.getValue(time) * gain;
- }
-
- private SignalProvider inputSignal_;
- private SignalProvider gain_;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/modules/Delay.java b/core/src/com/levien/synthesizer/core/model/modules/Delay.java
deleted file mode 100755
index d166b96..0000000
--- a/core/src/com/levien/synthesizer/core/model/modules/Delay.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model.modules;
-
-import java.util.Arrays;
-
-import com.levien.synthesizer.core.model.CachedSignalProvider;
-import com.levien.synthesizer.core.model.SignalProvider;
-import com.levien.synthesizer.core.model.SynthesisTime;
-
-/**
- * Delay is a module for recording sampled sound and playing it back later. It has 3 modes.
- * In regular mode, it outputs its input, attenuated by half.
- * In record mode, it also captures sound until it is stopped or the MAX_BUFFER_SIZE is reached.
- * In play mode, it plays back its output mixed with the recorded buffer in a loop.
- */
-public class Delay extends CachedSignalProvider {
- public Delay(SignalProvider source, SignalProvider mix) {
- source_ = source;
- mix_ = mix;
- buffer_ = new double[MAX_BUFFER_SIZE];
- current_ = 0;
- bufferSize_ = MAX_BUFFER_SIZE;
- Arrays.fill(buffer_, 0.0);
- playing_ = false;
- recording_ = false;
- }
-
- @Override
- protected synchronized double computeValue(SynthesisTime time) {
- double input = source_.getValue(time);
- double mix = mix_.getValue(time);
- if (playing_) {
- double output = mix * buffer_[current_] + (1.0 - mix) * input;
- current_ = (current_ + 1) % bufferSize_;
- return output;
- } else {
- if (recording_) {
- buffer_[bufferSize_++] = input;
- if (bufferSize_ >= MAX_BUFFER_SIZE) {
- stopRecording();
- }
- }
- return (1.0 - mix) * input;
- }
- }
-
- /**
- * Resets the buffer and changes to record mode.
- */
- public synchronized void startRecording() {
- playing_ = false;
- recording_ = true;
- current_ = 0;
- bufferSize_ = 0;
- }
-
- /**
- * Stops recording, but doesn't start playing.
- */
- public synchronized void stopRecording() {
- recording_ = false;
- current_ = 0;
- }
-
- /**
- * Starts playing what's recorded.
- */
- public synchronized void startPlaying() {
- playing_ = true;
- recording_ = false;
- current_ = 0;
- }
-
- /**
- * Stops playing and recording.
- */
- public synchronized void stopPlaying() {
- playing_ = false;
- recording_ = false;
- current_ = 0;
- }
-
- /**
- * Returns whether the module is in playing mode.
- */
- public synchronized boolean isPlaying() {
- return playing_;
- }
-
- /**
- * Returns whether the module is in record mode.
- */
- public synchronized boolean isRecording() {
- return recording_;
- }
-
- private SignalProvider source_;
- private SignalProvider mix_;
-
- private double[] buffer_;
- private int bufferSize_;
- private int current_;
-
- private boolean playing_;
- private boolean recording_;
-
- private final static int MAX_BUFFER_SIZE = 10;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/modules/Echo.java b/core/src/com/levien/synthesizer/core/model/modules/Echo.java
deleted file mode 100755
index fa347ae..0000000
--- a/core/src/com/levien/synthesizer/core/model/modules/Echo.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model.modules;
-
-import com.levien.synthesizer.core.model.CachedSignalProvider;
-import com.levien.synthesizer.core.model.SignalProvider;
-import com.levien.synthesizer.core.model.SynthesisTime;
-
-/**
- * The Echo module produces an echo effect by mixing its current input with its earlier input.
- */
-public class Echo extends CachedSignalProvider {
- /**
- * Creates a new Echo module.
- * @param source - The input to the echo module.
- * @param mix - How wet/dry the output is, i.e. the depth of the effect.
- * @param delay - The length of time in seconds between input and its first repetition.
- * @param sampleRateInHz - Sample rate, used to compute buffer size from delay time.
- */
- public Echo(SignalProvider source,
- SignalProvider mix,
- SignalProvider delay,
- double sampleRateInHz) {
- source_ = source;
- mix_ = mix;
- delay_ = delay;
- sampleRateInHz_ = sampleRateInHz;
- buffer_ = new double[MAX_BUFFER_SIZE];
- for (int i = 0; i < MAX_BUFFER_SIZE; ++i) {
- buffer_[i] = 0.0;
- }
- bufferSize_ = 0;
- current_ = 0;
- previousDelay_ = 0.0;
- }
-
- protected void maybeUpdateDelay(double delay) {
- // As an optimization, just bail if the delay value hasn't changed.
- if (previousDelay_ == delay) {
- return;
- }
- previousDelay_ = delay;
-
- int newBufferSize = 0;
- if (delay != 0.0) {
- newBufferSize = (int)Math.round(delay * sampleRateInHz_);
- }
- if (bufferSize_ == newBufferSize) {
- return;
- }
- bufferSize_ = newBufferSize;
- if (bufferSize_ < 1) {
- bufferSize_ = 0;
- }
- if (bufferSize_ > MAX_BUFFER_SIZE) {
- bufferSize_ = MAX_BUFFER_SIZE;
- }
- }
-
- @Override
- protected double computeValue(SynthesisTime time) {
- maybeUpdateDelay(delay_.getValue(time));
- double input = source_.getValue(time);
- double mix = mix_.getValue(time);
- if (bufferSize_ == 0) {
- return (1.0 - mix) * input;
- } else {
- double value = mix * buffer_[current_] + (1.0 - mix) * input;
- buffer_[current_] = value;
- current_ = (current_ + 1) % bufferSize_;
- return value;
- }
- }
-
- private SignalProvider source_;
- private SignalProvider mix_;
- private SignalProvider delay_;
-
- private double previousDelay_;
- private double[] buffer_;
- private int bufferSize_;
- private double sampleRateInHz_;
- private int current_;
-
- private final static int MAX_BUFFER_SIZE = 55125;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/modules/Glide.java b/core/src/com/levien/synthesizer/core/model/modules/Glide.java
deleted file mode 100644
index e23e97f..0000000
--- a/core/src/com/levien/synthesizer/core/model/modules/Glide.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model.modules;
-
-import com.levien.synthesizer.core.model.CachedFrequencyProvider;
-import com.levien.synthesizer.core.model.FrequencyProvider;
-import com.levien.synthesizer.core.model.SignalProvider;
-import com.levien.synthesizer.core.model.SynthesisTime;
-
-/**
- * Glide smooths changes in frequency over time.
- */
-public class Glide extends CachedFrequencyProvider {
- /**
- * Creates a Glide module to wrap source.
- * @param source - The input frequency to smooth.
- * @param rate - The time in seconds in which output should change to a new input.
- */
- public Glide(FrequencyProvider source, SignalProvider rate) {
- source_ = source;
- rate_ = rate;
- previousLogFrequency_ = 0.0;
- nextLogFrequency_ = 0.0;
- }
-
- public double computeLogFrequency(SynthesisTime time) {
- double currentLogFrequency = source_.getLogFrequency(time);
- double rate = rate_.getValue(time);
-
- // If rate is 0 seconds, then don't do anything.
- if (rate == 0.0) {
- previousLogFrequency_ = currentLogFrequency;
- nextLogFrequency_ = currentLogFrequency;
- return currentLogFrequency;
- }
-
- // It hasn't changed, so don't do anything.
- if (currentLogFrequency == previousLogFrequency_ &&
- nextLogFrequency_ == previousLogFrequency_) {
- return currentLogFrequency;
- }
-
- // See where we are, based on where we were last heading.
- double timeSinceChange = time.getAbsoluteTime() - switchTime_;
- double output;
- if (timeSinceChange > rate) {
- output = nextLogFrequency_;
- } else {
- output = previousLogFrequency_ +
- (timeSinceChange / rate) * (nextLogFrequency_ - previousLogFrequency_);
- }
-
- // Adjust if there is a new destination.
- if (currentLogFrequency != nextLogFrequency_) {
- previousLogFrequency_ = output;
- nextLogFrequency_ = currentLogFrequency;
- switchTime_ = time.getAbsoluteTime();
- }
-
- return output;
- }
-
- // The wrapped frequency provider to take as input and output smoothed.
- private FrequencyProvider source_;
-
- // The time in seconds in which output should change to a new input.
- private SignalProvider rate_;
-
- // The log frequency that was being output last time the input switched.
- private double previousLogFrequency_;
-
- // The log frequency of the input that this module is moving toward.
- private double nextLogFrequency_;
-
- // The last time that in the input frequency changed.
- private double switchTime_;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/modules/LowPassFilter.java b/core/src/com/levien/synthesizer/core/model/modules/LowPassFilter.java
deleted file mode 100644
index 8d8b31b..0000000
--- a/core/src/com/levien/synthesizer/core/model/modules/LowPassFilter.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model.modules;
-
-import com.levien.synthesizer.core.model.CachedSignalProvider;
-import com.levien.synthesizer.core.model.SignalProvider;
-import com.levien.synthesizer.core.model.SynthesisTime;
-
-/**
- * A very simple low-pass filter.
- */
-public class LowPassFilter extends CachedSignalProvider {
- /**
- * Creates a LowPassFilter with the given parameters.
- * @param source - The input signal to filter.
- * @param cutoff - "Alpha" parameter that controls the cutoff frequency.
- */
- public LowPassFilter(SignalProvider source, SignalProvider cutoff) {
- source_ = source;
- alpha_ = cutoff;
- previousValue_ = 0.0;
- }
-
- public double computeValue(SynthesisTime time) {
- double alpha = alpha_.getValue(time);
- double output = 0.0;
- if (alpha != 0) {
- double signal = source_.getValue(time);
- output = previousValue_ + alpha * (signal - previousValue_);
- previousValue_ = output;
- } else {
- output = previousValue_;
- }
- return output;
- }
-
- // The filter parameters.
- private SignalProvider source_;
- private SignalProvider alpha_;
-
- private double previousValue_;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/modules/Mixer.java b/core/src/com/levien/synthesizer/core/model/modules/Mixer.java
deleted file mode 100755
index 950a5be..0000000
--- a/core/src/com/levien/synthesizer/core/model/modules/Mixer.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model.modules;
-
-import com.levien.synthesizer.core.model.SignalProvider;
-import com.levien.synthesizer.core.model.SynthesisTime;
-
-/**
- * Mixer outputs a weighted average of two input signals.
- * A "balance" of 0.0 outputs signal 1, and a balance of 1.0 outputs signal 2.
- * The balance can be changed over time.
- */
-public class Mixer implements SignalProvider {
- /**
- * Creates a new Mixer.
- * @param signal1 - Any input signal module.
- * @param signal2 - Any input signal module.
- * @param balance - A module outputting the weight to use when averaging.
- */
- public Mixer(SignalProvider signal1, SignalProvider signal2, SignalProvider balance) {
- signal1_ = signal1;
- signal2_ = signal2;
- balance_ = balance;
- }
-
- /**
- * Returns the average of the input signals, weighted by balance.
- */
- public double getValue(SynthesisTime time) {
- double balance = balance_.getValue(time);
- // As an optimization, don't compute any signal that's not needed.
- if (balance == 0.0) {
- return signal1_.getValue(time);
- } else if (balance == 1.0) {
- return signal2_.getValue(time);
- } else {
- return (1.0 - balance) * signal1_.getValue(time) + balance * signal2_.getValue(time);
- }
- }
-
- private SignalProvider signal1_;
- private SignalProvider signal2_;
- private SignalProvider balance_;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/modules/Tremolo.java b/core/src/com/levien/synthesizer/core/model/modules/Tremolo.java
deleted file mode 100644
index 2f3878b..0000000
--- a/core/src/com/levien/synthesizer/core/model/modules/Tremolo.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model.modules;
-
-import com.levien.synthesizer.core.model.SignalProvider;
-import com.levien.synthesizer.core.model.SynthesisTime;
-
-/**
- * Module to modulate an amplitude over time based on a modulator signal. Its output is intended to
- * be fed into an amplifier.
- */
-public class Tremolo implements SignalProvider {
- /**
- * Creates a Tremolo module.
- * @param modulator - Waveform that modulates the amplitude.
- * @param depth - Depth of amplitude modulation.
- */
- public Tremolo(SignalProvider modulator, SignalProvider depth) {
- modulator_ = modulator;
- depth_ = depth;
- }
-
- public double getValue(SynthesisTime time) {
- double modulator = modulator_.getValue(time);
- double depth = depth_.getValue(time);
- return (modulator * (depth / 2.0)) + (1.0 - depth / 2.0);
- }
-
- // Waveform that modulates the amplitude.
- private SignalProvider modulator_;
-
- // Depth of amplitude modulation.
- private SignalProvider depth_;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/modules/Tuner.java b/core/src/com/levien/synthesizer/core/model/modules/Tuner.java
deleted file mode 100644
index bb7e7ee..0000000
--- a/core/src/com/levien/synthesizer/core/model/modules/Tuner.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model.modules;
-
-import com.levien.synthesizer.core.model.FrequencyProvider;
-import com.levien.synthesizer.core.model.SignalProvider;
-import com.levien.synthesizer.core.model.SynthesisTime;
-
-/**
- * Module to modify the output of a frequency provider.
- */
-public class Tuner implements FrequencyProvider {
- /**
- * Creates a Tuner module to wrap source.
- * @param input - The base log frequency.
- * @param shift - The amount to alter it.
- */
- public Tuner(FrequencyProvider input, SignalProvider shift) {
- input_ = input;
- shift_ = shift;
- }
-
- public double getLogFrequency(SynthesisTime time) {
- double input = input_.getLogFrequency(time);
- double shift = shift_.getValue(time);
- return input + shift;
- }
-
- // The wrapped frequency provider to take as input.
- private FrequencyProvider input_;
-
- // The amount to alter the signal.
- private SignalProvider shift_;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/modules/WaveformSelector.java b/core/src/com/levien/synthesizer/core/model/modules/WaveformSelector.java
deleted file mode 100644
index 6cff8b9..0000000
--- a/core/src/com/levien/synthesizer/core/model/modules/WaveformSelector.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model.modules;
-
-import java.util.ArrayList;
-
-import com.levien.synthesizer.core.model.FrequencyProvider;
-import com.levien.synthesizer.core.model.SignalProvider;
-import com.levien.synthesizer.core.model.SynthesisTime;
-import com.levien.synthesizer.core.model.WaveformInput;
-import com.levien.synthesizer.core.model.oscillator.Noise;
-import com.levien.synthesizer.core.model.oscillator.Sawtooth;
-import com.levien.synthesizer.core.model.oscillator.Sine;
-import com.levien.synthesizer.core.model.oscillator.Square;
-import com.levien.synthesizer.core.model.oscillator.Triangle;
-
-/**
- * Module that outputs a waveform from a selectable set of oscillators.
- */
-public class WaveformSelector implements SignalProvider {
- /**
- * Constructs a waveform selector with no waveforms available.
- * @param waveform - The source for which waveform to use at any given time.
- */
- public WaveformSelector(WaveformInput waveform) {
- waveform_ = waveform;
- sources_ = new ArrayList();
- }
-
- /**
- * Adds a source for a new waveform type.
- */
- public synchronized void addWaveform(String waveform, SignalProvider source) {
- int id = waveform_.addWaveform(waveform);
- while (sources_.size() < id + 1) {
- sources_.add(null);
- }
- sources_.set(id, source);
- }
-
- /**
- * Returns the output of the source associated with the selected waveform.
- */
- public synchronized double getValue(SynthesisTime time) {
- int selected = waveform_.getSelected();
- SignalProvider provider = sources_.get(selected);
- if (provider != null) {
- return provider.getValue(time);
- } else {
- return 0.0;
- }
- }
-
- /**
- * Adds the standard waveforms to this selector.
- */
- public synchronized void addDefaultWaveforms(FrequencyProvider frequency) {
- addWaveform(WaveformInput.SINE, new Sine(frequency));
- addWaveform(WaveformInput.TRIANGLE, new Triangle(frequency));
- addWaveform(WaveformInput.SQUARE, new Square(frequency));
- addWaveform(WaveformInput.SAWTOOTH, new Sawtooth(frequency));
- addWaveform(WaveformInput.NOISE, new Noise(frequency));
- }
-
- // Instances of each waveform type.
- private ArrayList sources_;
-
- // The currently selected waveform.
- private WaveformInput waveform_;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/oscillator/DrawbarOrgan.java b/core/src/com/levien/synthesizer/core/model/oscillator/DrawbarOrgan.java
deleted file mode 100644
index 06ed36a..0000000
--- a/core/src/com/levien/synthesizer/core/model/oscillator/DrawbarOrgan.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model.oscillator;
-
-import com.levien.synthesizer.core.model.FrequencyProvider;
-import com.levien.synthesizer.core.model.SignalProvider;
-import com.levien.synthesizer.core.model.SynthesisTime;
-
-/**
- * An oscillator module that emulates a set of tone wheels for a drawbar organ.
- */
-public class DrawbarOrgan extends Oscillator {
- /**
- * Creates a new drawbar organ with the given pitch and inputs for the level of each drawbar.
- */
- public DrawbarOrgan(FrequencyProvider frequency,
- SignalProvider subFundamental,
- SignalProvider subThirdHarmonic,
- SignalProvider fundamental,
- SignalProvider secondHarmonic,
- SignalProvider thirdHarmonic,
- SignalProvider fourthHarmonic,
- SignalProvider fifthHarmonic,
- SignalProvider sixthHarmonic,
- SignalProvider eighthHarmonic) {
- super(frequency);
-
- depth_ = new SignalProvider[9];
- oscillator_ = new Sine[9];
-
- depth_[0] = subFundamental;
- oscillator_[0] = new Sine(new FrequencyProvider() {
- public double getLogFrequency(SynthesisTime time) {
- return frequency_.getLogFrequency(time) - 1.0;
- }
- });
-
- depth_[1] = subThirdHarmonic;
- oscillator_[1] = new Sine(new FrequencyProvider() {
- public double getLogFrequency(SynthesisTime time) {
- return frequency_.getLogFrequency(time) + 0.5849625; // log2(3) =~ 7/12
- }
- });
-
- depth_[2] = fundamental;
- oscillator_[2] = new Sine(frequency);
-
- depth_[3] = secondHarmonic;
- oscillator_[3] = new Sine(new FrequencyProvider() {
- public double getLogFrequency(SynthesisTime time) {
- return frequency_.getLogFrequency(time) + 1.0;
- }
- });
-
- depth_[4] = thirdHarmonic;
- oscillator_[4] = new Sine(new FrequencyProvider() {
- public double getLogFrequency(SynthesisTime time) {
- return frequency_.getLogFrequency(time) + 1.5849625; // 1 + log2(3) =~ 19/12
- }
- });
-
- depth_[5] = fourthHarmonic;
- oscillator_[5] = new Sine(new FrequencyProvider() {
- public double getLogFrequency(SynthesisTime time) {
- return frequency_.getLogFrequency(time) + 2.0;
- }
- });
-
- depth_[6] = fifthHarmonic;
- oscillator_[6] = new Sine(new FrequencyProvider() {
- public double getLogFrequency(SynthesisTime time) {
- return frequency_.getLogFrequency(time) + 2.3219281; // 1 + log2(5) =~ 28/12;
- }
- });
-
- depth_[7] = sixthHarmonic;
- oscillator_[7] = new Sine(new FrequencyProvider() {
- public double getLogFrequency(SynthesisTime time) {
- return frequency_.getLogFrequency(time) + 2.5849625; // 1 + log2(6) =~ 31/12;
- }
- });
-
- depth_[8] = eighthHarmonic;
- oscillator_[8] = new Sine(new FrequencyProvider() {
- public double getLogFrequency(SynthesisTime time) {
- return frequency_.getLogFrequency(time) + 3.0;
- }
- });
- }
-
- /**
- * Makes a weighted average of the value from each tone wheel.
- */
- public double computeValue(SynthesisTime time) {
- double output = 0.0;
- double denominator = 0.0;
- for (int i = 0; i < oscillator_.length; ++i) {
- double depth = depth_[i].getValue(time);
- if (depth != 0.0) {
- output += (depth * oscillator_[i].getValue(time));
- denominator += depth;
- }
- }
- if (denominator == 0.0) {
- return 0.0;
- }
- return output / denominator;
- }
-
- // How much each drawbar is pulled out.
- private SignalProvider[] depth_;
-
- // The set of underlying sine oscillators for each tone wheel.
- private Sine[] oscillator_;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/oscillator/KarplusStrong.java b/core/src/com/levien/synthesizer/core/model/oscillator/KarplusStrong.java
deleted file mode 100644
index 92683e9..0000000
--- a/core/src/com/levien/synthesizer/core/model/oscillator/KarplusStrong.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model.oscillator;
-
-import com.levien.synthesizer.core.model.Envelope;
-import com.levien.synthesizer.core.model.FrequencyProvider;
-import com.levien.synthesizer.core.model.SignalProvider;
-import com.levien.synthesizer.core.model.SynthesisTime;
-import java.util.Arrays;
-
-/**
- * Karplus-Strong string/drum synthesis algorithm.
- *
- * @param frequency - The frequency of the note produced.
- * @param blend - Blend factor. Closer to 0 sounds more like a string, closer to 1 more like a drum.
- * @param stretch - How fast the vibration of the string should decay.
- * @param excitement - How noisy (i.e. random) the initial pluck should be.
- * @param sampleRateInHz - The sample rate, used with pitch to compute KS buffer size.
- */
-public class KarplusStrong extends Oscillator implements Envelope {
- public KarplusStrong(FrequencyProvider frequency,
- SignalProvider blend,
- SignalProvider stretch,
- SignalProvider excitement,
- double sampleRateInHz) {
- super(frequency);
- sampleRateInHz_ = sampleRateInHz;
- buffer_ = new double[kMaxBufferSize];
- Arrays.fill(buffer_, 0.0);
- bufferSize_ = 0;
- current_ = 0;
-
- blend_ = blend;
- stretch_ = stretch;
- excitement_ = excitement;
- }
-
- @Override
- protected synchronized double computeValue(SynthesisTime time) {
- if (current_ == 0) {
- // We've looped around to the beginning of the buffer, so take the opportunity to resize.
- bufferSize_ =
- (int)Math.round(sampleRateInHz_ / (Math.pow(2.0, frequency_.getLogFrequency(time))));
- if (bufferSize_ > kMaxBufferSize) {
- bufferSize_ = kMaxBufferSize;
- }
- }
-
- // If the frequency is so high the buffer disappears, then we just can't do anything.
- if (bufferSize_ == 0) {
- trigger_ = false;
- return 0.0;
- }
-
- // The "string" has been "plucked". Fill the buffer with noise.
- if (trigger_) {
- trigger_ = false;
- double excitement = excitement_.getValue(time);
- for (int i = 0; i < kMaxBufferSize; ++i) {
- if (excitement == 0.0) {
- // Just an optimization.
- buffer_[i] = 0.5;
- } else {
- buffer_[i] = excitement * (Math.random() * 2.0 - 1.0);
- }
- }
- }
-
- // Process the buffer.
- double output = buffer_[current_];
- double blend = blend_.getValue(time);
- double stretch = 1.0 - stretch_.getValue(time); // Invert stretch so it's more intuitive.
- double direction = (blend == 0.0 || (blend != 1.0 && blend <= Math.random())) ? -1.0 : 1.0;
- double magnitude = 0.0;
- if (stretch == 0.0 || (stretch != 1.0 && stretch <= Math.random())) {
- magnitude = buffer_[current_];
- } else {
- magnitude = (buffer_[current_] + previousOutput_) / 2.0;
- }
- buffer_[current_] = direction * magnitude;
- previousOutput_ = output;
- current_ = (current_ + 1) % bufferSize_;
- return output;
- }
-
- /**
- * Doesn't really do anything at this time.
- */
- public synchronized void turnOff() {
- gate_ = false;
- }
-
- /**
- * Causes the string to be plucked by setting trigger_ to true.
- */
- public synchronized void turnOn(boolean retriggerIfOn) {
- if (gate_ && !retriggerIfOn) {
- return;
- }
- trigger_ = true;
- gate_ = true;
- }
-
- private double[] buffer_;
- private int bufferSize_;
- private double sampleRateInHz_;
- private int current_;
- private double previousOutput_;
-
- // Blend factor. Closer to 0 sounds more like a string. Closer to 1 sounds more like a drum.
- private SignalProvider blend_;
-
- // How fast the vibration of the string should decay.
- private SignalProvider stretch_;
-
- // How noisy (i.e. random) the initial pluck should be.
- private SignalProvider excitement_;
-
- private boolean trigger_;
- private boolean gate_;
-
- // The max buffer size is the highest sample rate divided by the lowest frequency (20 Hz).
- private final static int kMaxBufferSize = 44100/20;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/oscillator/Noise.java b/core/src/com/levien/synthesizer/core/model/oscillator/Noise.java
deleted file mode 100755
index f4589a2..0000000
--- a/core/src/com/levien/synthesizer/core/model/oscillator/Noise.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model.oscillator;
-
-import com.levien.synthesizer.core.model.FrequencyProvider;
-import com.levien.synthesizer.core.model.SynthesisTime;
-
-/**
- * An oscillator module that outputs random values in the range [-1, 1].
- */
-public class Noise extends Oscillator {
- public Noise(FrequencyProvider frequency) {
- super(frequency);
- }
-
- public double computeValue(SynthesisTime time) {
- return Math.random() * 2.0 - 1.0;
- }
-}
diff --git a/core/src/com/levien/synthesizer/core/model/oscillator/Oscillator.java b/core/src/com/levien/synthesizer/core/model/oscillator/Oscillator.java
deleted file mode 100755
index ddb232a..0000000
--- a/core/src/com/levien/synthesizer/core/model/oscillator/Oscillator.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model.oscillator;
-
-import com.levien.synthesizer.core.model.CachedSignalProvider;
-import com.levien.synthesizer.core.model.FrequencyProvider;
-
-/**
- * Subclass for any oscillator -- any module that outputs a waveform based on a given frequency.
- * The range of the output is [-1, 1.0].
- */
-public abstract class Oscillator extends CachedSignalProvider {
- /**
- * Constructor for subclasses to store the frequency.
- */
- public Oscillator(FrequencyProvider frequency) {
- frequency_ = frequency;
- }
-
- protected FrequencyProvider frequency_;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/oscillator/Sawtooth.java b/core/src/com/levien/synthesizer/core/model/oscillator/Sawtooth.java
deleted file mode 100755
index c32ddba..0000000
--- a/core/src/com/levien/synthesizer/core/model/oscillator/Sawtooth.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model.oscillator;
-
-import com.levien.synthesizer.core.model.FrequencyProvider;
-import com.levien.synthesizer.core.model.SynthesisTime;
-
-/**
- * An oscillator module that outputs a sawtooth wave.
- */
-public class Sawtooth extends Oscillator {
- public Sawtooth(FrequencyProvider frequency) {
- super(frequency);
- value_ = 0.0;
- currentFrequency_ = 1.0;
- }
-
- public double computeValue(SynthesisTime time) {
- // The output value drops until it is below -1.0, then shoots up to 1.0.
- value_ -= (2.0 * currentFrequency_ * time.getDeltaTime());
- while (value_ <= -1.0) {
- // Frequency is only updated at the end of each cycle.
- double nextFrequency = Math.pow(2.0, frequency_.getLogFrequency(time));
- currentFrequency_ = nextFrequency;
- // We can't just set to 1.0. The signal should have decreased from 1.0 by the amount it
- // actually decreased below -1.0.
- value_ += 2.0;
- }
- return value_;
- }
-
- // The most recent output value.
- private double value_;
-
- // The current frequency of the waveform.
- private double currentFrequency_;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/oscillator/Sine.java b/core/src/com/levien/synthesizer/core/model/oscillator/Sine.java
deleted file mode 100755
index 865a168..0000000
--- a/core/src/com/levien/synthesizer/core/model/oscillator/Sine.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model.oscillator;
-
-import com.levien.synthesizer.core.model.FrequencyProvider;
-import com.levien.synthesizer.core.model.SynthesisTime;
-
-/**
- * An oscillator module that outputs a sine wave.
- */
-public class Sine extends Oscillator {
- public Sine(FrequencyProvider frequency) {
- super(frequency);
- value_ = 0.0;
- offset_ = 0.0;
- currentLogFrequency_ = 0.0;
- currentFrequency_ = 1.0;
- }
-
- public double computeValue(SynthesisTime time) {
- // Compute the output using the current frequency.
- value_ = Math.sin(2 * Math.PI * currentFrequency_ * (time.getAbsoluteTime() + offset_));
-
- // If the frequency is supposed to change, change the phase offset to where the new frequency
- // would be outputting the same current value.
- double nextLogFrequency = frequency_.getLogFrequency(time);
- if (currentLogFrequency_ != nextLogFrequency) {
- double nextFrequency = Math.pow(2.0, nextLogFrequency);
- offset_ = ((time.getAbsoluteTime() + offset_) * currentFrequency_ / nextFrequency) -
- time.getAbsoluteTime();
- currentLogFrequency_ = nextLogFrequency;
- currentFrequency_ = nextFrequency;
- }
-
- return value_;
- }
-
- // Most recently output value.
- private double value_;
-
- // How far out of phrase the wave is from one starting at time 0.
- private double offset_;
-
- // Amplitude and frequency for the current output value.
- private double currentLogFrequency_;
- private double currentFrequency_;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/oscillator/Square.java b/core/src/com/levien/synthesizer/core/model/oscillator/Square.java
deleted file mode 100755
index b8b88fa..0000000
--- a/core/src/com/levien/synthesizer/core/model/oscillator/Square.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model.oscillator;
-
-import com.levien.synthesizer.core.model.FrequencyProvider;
-import com.levien.synthesizer.core.model.SynthesisTime;
-
-/**
- * An oscillator module that outputs a square wave.
- */
-public class Square extends Oscillator {
- public Square(FrequencyProvider frequency) {
- super(frequency);
- sine_ = new Sine(frequency);
- }
-
- public double computeValue(SynthesisTime time) {
- // The easiest way to make a square wave is to take a sine wave and round it to -1 or 1.
- if (sine_.getValue(time) > 0.0) {
- return 1.0;
- } else {
- return -1.0;
- }
- }
-
- private Sine sine_;
-}
diff --git a/core/src/com/levien/synthesizer/core/model/oscillator/Triangle.java b/core/src/com/levien/synthesizer/core/model/oscillator/Triangle.java
deleted file mode 100755
index aaea06b..0000000
--- a/core/src/com/levien/synthesizer/core/model/oscillator/Triangle.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.model.oscillator;
-
-import com.levien.synthesizer.core.model.FrequencyProvider;
-import com.levien.synthesizer.core.model.SynthesisTime;
-
-/**
- * An oscillator module that outputs a triangle wave.
- */
-public class Triangle extends Oscillator {
- public Triangle(FrequencyProvider frequency) {
- super(frequency);
- sawtooth_ = new Sawtooth(frequency);
- }
-
- public double computeValue(SynthesisTime time) {
- // It's a simple mathematical transformation to convert a sawtooth to a triangle.
- return -2.0 * Math.abs(sawtooth_.getValue(time)) + 1.0;
- }
-
- private Sawtooth sawtooth_;
-}
diff --git a/core/src/com/levien/synthesizer/core/music/EventComparator.java b/core/src/com/levien/synthesizer/core/music/EventComparator.java
deleted file mode 100644
index 651302a..0000000
--- a/core/src/com/levien/synthesizer/core/music/EventComparator.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.music;
-
-import java.util.Comparator;
-
-import com.levien.synthesizer.core.music.Music.EventOrBuilder;
-
-/**
- * A few comparators for sorting lists of Events (like in a score).
- */
-public class EventComparator {
- /**
- * Sorts by the start times of the events.
- */
- public static Comparator byStart() {
- return new Comparator() {
- public int compare(EventOrBuilder event, EventOrBuilder other) {
- if (other.getStart() == event.getStart()) {
- if (other.hasKeyEvent() && !event.hasKeyEvent()) {
- return -1;
- } else if (!other.hasKeyEvent() && event.hasKeyEvent()) {
- return 1;
- } else if (other.getEnd() == event.getEnd()) {
- return 0;
- } else if (other.getEnd() > event.getEnd()) {
- return 1;
- } else {
- return -1;
- }
- } else if (other.getStart() < event.getStart()) {
- return 1;
- } else {
- return -1;
- }
- }
- };
- }
-
- /**
- * Sorts by the end times of the events.
- */
- public static Comparator byEnd() {
- return new Comparator() {
- public int compare(EventOrBuilder event, EventOrBuilder other) {
- if (other.getEnd() == event.getEnd()) {
- if (other.hasKeyEvent() && !event.hasKeyEvent()) {
- return 1;
- } else if (!other.hasKeyEvent() && event.hasKeyEvent()) {
- return -1;
- } else if (other.getStart() == event.getStart()) {
- return 0;
- } else if (other.getStart() < event.getStart()) {
- return -1;
- } else {
- return 1;
- }
- } else if (other.getEnd() < event.getEnd()) {
- return 1;
- } else {
- return -1;
- }
- }
- };
- }
-}
diff --git a/core/src/com/levien/synthesizer/core/music/Music.proto b/core/src/com/levien/synthesizer/core/music/Music.proto
deleted file mode 100644
index 1848c0b..0000000
--- a/core/src/com/levien/synthesizer/core/music/Music.proto
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package synthesizer_core_music;
-
-option java_package = "com.levien.synthesizer.core.music";
-
-// An Event is one item in a score. It has a start and end time, and information about what
-// happens at that time, such as what note is played, and on what channel (instrument).
-message Event {
- // The start time of the event in measures from the beginning of the score.
- optional double start = 1;
-
- // The end time of the event.
- optional double end = 2;
-
- // The start time before "snapping to" the nearest note in the editor.
- optional double unsnapped_start = 3;
-
- // The end time before "snapping to" the nearest note in the editor.
- optional double unsnapped_end = 4;
-
- // For a key event, the key/note being pressed. For other events, this is just where it shows up
- // in the score. For example, a loop event shows on a certain key just because that makes them
- // easier to edit.
- optional int32 key = 5;
-
- // The key before before "snapping to" the nearest whole key in the editor.
- // This can hold a fractional key, which can represent a valid frequency between two notes,
- // which might be valid for some synthesizers, but not for midi output.
- optional double unsnapped_key = 6;
-
- // Is this event selected in the UI?
- optional bool selected = 7;
-
- // An event where a key is pressed.
- optional KeyEvent key_event = 8;
-
- // An event where that defines a loop.
- optional LoopEvent loop_event = 9;
-}
-
-// An event where a key is pressed at the beginning and released at the end.
-message KeyEvent {
- // The channel/instrument to play the note on.
- optional int32 channel = 1;
-}
-
-// An event where playback jumps from the end to the beginning a certain number of times.
-message LoopEvent {
- // The total number of times to loop.
- optional int32 count = 1;
-
- // The number of times left to loop in the current playback.
- optional int32 count_remaining = 2;
-}
-
-// A score, representing a series of synthesizer events that can be played.
-message Score {
- // The set of events, in no particular order.
- repeated Event event = 1;
-}
diff --git a/core/src/com/levien/synthesizer/core/music/Note.java b/core/src/com/levien/synthesizer/core/music/Note.java
deleted file mode 100755
index 49a8428..0000000
--- a/core/src/com/levien/synthesizer/core/music/Note.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2010 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.music;
-
-/**
- * Collection of static methods dealing with musical notes.
- */
-public class Note {
- /**
- * Determines the log frequency of a note in 12 tone equal temperament (12-TET).
- * @param note - the note, a value from one of the constants in this class.
- * @param octave - the octave of the note.
- */
- public static double computeLog12TET(int note, int octave) {
- return FACTOR + ((((12 * octave) + (note - 9) + 1) - 49) / 12.0);
- }
-
- /**
- * Returns the note, or midi key, that corresponds to the given log frequency.
- * @param logFrequency - the log frequency that corresponds to a note.
- * @return - the nearest note to that frequency.
- */
- public static int getKeyforLog12TET(double logFrequency) {
- return (int)(12.0 * (logFrequency - FACTOR) + 57.5);
- }
-
- /**
- * Returns true if the note is natural, i.e. not a sharp or flat.
- * @param note - the note, a value from one of the constants in this class.
- */
- public static boolean isNatural(int note) {
- return NATURAL[note % NATURAL.length];
- }
-
- /**
- * Returns a printable name for the given note.
- * @param note - the note, a value from one of the constants in this class.
- */
- public static String getName(int note) {
- return NAMES[note];
- }
-
- // Note frequencies in 12-TET are defined relative to log2 of A4 (440Hz).
- // There's no reason to redo the log conversion every time a frequency is computed.
- private static final double FACTOR = Math.log(440.0) / Math.log(2.0);
-
- // Constants for each of the possible notes.
- public static final int NONE = -1;
- public static final int C = 0;
- public static final int C_SHARP = 1;
- public static final int D_FLAT = 1;
- public static final int D = 2;
- public static final int D_SHARP = 3;
- public static final int E_FLAT = 3;
- public static final int E = 4;
- public static final int F = 5;
- public static final int F_SHARP = 6;
- public static final int G_FLAT = 6;
- public static final int G = 7;
- public static final int G_SHARP = 8;
- public static final int A_FLAT = 8;
- public static final int A = 9;
- public static final int A_SHARP = 10;
- public static final int B_FLAT = 10;
- public static final int B = 11;
-
- // Constants for intervals between notes.
- public static final double HALF_STEP = 1.0f / 12.0f;
- public static final double WHOLE_STEP = 1.0f / 6.0f;
- public static final double OCTAVE = 1.0f;
-
- // A simple map of which notes are natural.
- private static final boolean[] NATURAL = {
- true, false, true, false, true, true, false, true, false, true, false, true };
-
- // A displayable name for each note.
- private static final String[] NAMES = {
- "C", "C#", "D", "Eb", "E", "F", "F#", "G", "Ab", "A", "Bb", "B"
- };
-}
diff --git a/core/src/com/levien/synthesizer/core/music/ScorePlayer.java b/core/src/com/levien/synthesizer/core/music/ScorePlayer.java
deleted file mode 100644
index 85e0fb7..0000000
--- a/core/src/com/levien/synthesizer/core/music/ScorePlayer.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.music;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.ListIterator;
-import java.util.PriorityQueue;
-import java.util.logging.Logger;
-
-import com.levien.synthesizer.core.midi.MidiListener;
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
-import com.levien.synthesizer.core.music.Music.Event;
-import com.levien.synthesizer.core.music.Music.Score;
-
-/**
- * Methods for playing a score using a synthesizer.
- * @see ScorePlayerListener
- */
-public class ScorePlayer {
- /**
- * Creates a new ScorePlayer.
- */
- public ScorePlayer() {
- logger_ = Logger.getLogger(ScorePlayer.class.getName());
- playing_ = false;
- }
-
- /**
- * Merges identical loop events in a sorted list of events. Since having two loops over the same
- * time period would normally make them multiplicative, and that isn't useful, this changes that
- * one situation to make them additive. That way, you can have a segment that play three times
- * without having to create any events that have a repeat count other than one.
- */
- private void mergeIdenticalLoopEvents(ArrayList startList) {
- for (int i = 0; i < startList.size(); ++i) {
- if (i+1 < startList.size() &&
- startList.get(i).hasLoopEvent() &&
- startList.get(i+1).hasLoopEvent() &&
- startList.get(i).getStart() == startList.get(i+1).getStart() &&
- startList.get(i).getEnd() == startList.get(i+1).getEnd()) {
- startList.get(i).getLoopEventBuilder().setCount(
- startList.get(i).getLoopEventBuilder().getCount() +
- startList.get(i+1).getLoopEventBuilder().getCount());
- startList.remove(i+1);
- i--;
- }
- }
- }
-
- /**
- * Plays the given score using the given synthesizer. Returns immediately, while the music plays
- * in a separate thread.
- *
- * @param synth - the synthesizer to use for output.
- * @param score - the score to play.
- * @param beatsPerMinute - the tempo to play.
- * @param beatsPerMeasure - the time signature.
- * @param listener - the listener to notify of events.
- */
- public synchronized void startPlaying(MidiListener synth,
- Score score,
- double beatsPerMinute,
- int beatsPerMeasure,
- ScorePlayerListener listener) {
- if (playing_) {
- logger_.warning("startPlaying called while already playing.");
- return;
- }
-
- // Copy the sequence so that it's safe to modify it while it's playing asynchronously.
- ArrayList startList =
- new ArrayList(Score.newBuilder(score).getEventBuilderList());
- Collections.sort(startList, EventComparator.byStart());
- mergeIdenticalLoopEvents(startList);
- starts_ = startList.listIterator();
-
- ends_ = new PriorityQueue(startList.size(), EventComparator.byEnd());
-
- // Setup the internal state.
- synth_ = synth;
- listener_ = listener;
- beatsPerMinute_ = beatsPerMinute;
- beatsPerMeasure_ = beatsPerMeasure;
- playing_ = true;
- stop_ = false;
- currentTime_ = 0.0;
-
- listener_.onStart();
-
- new Thread("ScorePlayer.startPlaying()") {
- public void run() {
- logger_.info("ScorePlayer.startPlaying() thread running.");
- while (true) {
- // While we have the lock, we'll need to see how long to sleep until the next iteration of
- // the loop. This variable will contain that delay at the end of the loop.
- long delay;
-
- synchronized (ScorePlayer.this) {
- onTimeUpdate();
-
- // Check if it's time to stop.
- if (stop_) {
- playing_ = false;
-
- // Okay, now finish off all of the events that have been started.
- while (!ends_.isEmpty()) {
- Event.Builder event = ends_.remove();
- if (event.hasKeyEvent()) {
- synth_.onNoteOff(event.getKeyEvent().getChannel(), event.getKey(), 0);
- }
- }
-
- listener_.onStop();
- logger_.info("Finished playing.");
- break;
- }
-
- // See if there are more events to process.
- if (!starts_.hasNext() && ends_.isEmpty()) {
- // There are no more events to process.
- stop_ = true;
- continue;
- }
-
- // There are more events. See when the next one should be processed.
- boolean isEnd;
- double targetTime;
- if (!starts_.hasNext()) {
- // All of the start events are over. The next event will need to be an end event.
- isEnd = true;
- targetTime = getSecondsPerMeasure() * ends_.peek().getEnd();
- } else if (ends_.isEmpty()) {
- // There are no end events queued up yet. The next event will need to be a start.
- isEnd = false;
- targetTime = getSecondsPerMeasure() * starts_.next().getStart();
- starts_.previous();
- } else {
- // We'll need to process either a start or an end, whichever is first.
- if (ends_.peek().getEnd() <= peek(starts_).getStart()) {
- // Process the next end.
- isEnd = true;
- targetTime = getSecondsPerMeasure() * ends_.peek().getEnd();
- } else {
- // Process the next start.
- isEnd = false;
- targetTime = getSecondsPerMeasure() * peek(starts_).getStart();
- }
- }
-
- // See if we need to process an event now.
- if (currentTime_ >= targetTime) {
- // Yes, we do.
- if (isEnd) {
- Event.Builder event = ends_.remove();
- if (event.hasKeyEvent()) {
- synth_.onNoteOff(event.getKeyEvent().getChannel(),
- event.getKey(), 0);
- } else if (event.hasLoopEvent()) {
- if (!event.getLoopEvent().hasCountRemaining()) {
- event.getLoopEventBuilder().setCountRemaining(event.getLoopEvent().getCount());
- }
- if (event.getLoopEvent().getCountRemaining() > 0) {
- // Okay, it's time to loop.
- // TODO(klimt): Ideally, we'd kill all note events currently alive, but we
- // don't want to kill any of the loop events, so it's a little tricky.
- // while (!ends_.isEmpty()) {
- // Event.Builder eventToStop = ends_.remove();
- // if (eventToStop.hasKeyEvent()) {
- // synth_.onNoteOff(eventToStop.getKeyEvent().getChannel(),
- // eventToStop.getKey(), 0);
- // }
- // }
- // Now, rewind the start list until it's before the start time.
- while (starts_.previous() != event) {
- // Rewind.
- }
- // Okay, now update the current time.
- currentTime_ = getSecondsPerMeasure() * event.getStart();
- targetTime = currentTime_;
- event.getLoopEventBuilder().setCountRemaining(
- event.getLoopEvent().getCountRemaining() - 1);
- } else {
- // We're finished with this loop, so we're moving on.
- event.getLoopEventBuilder().clearCountRemaining();
- }
- }
- } else {
- Event.Builder event = starts_.next();
- if (event.hasKeyEvent()) {
- synth_.onNoteOn(event.getKeyEvent().getChannel(), event.getKey(), 127);
- }
- // We started the event, so let's make sure we end it eventually. :)
- ends_.add(event);
- }
- // Okay, move on to the next event.
- continue;
- }
-
- // If we got this far, we'll need to sleep until the next event. See how long.
- delay = (long)((targetTime - currentTime_) * 1000.0);
- } // synchronized (ScorePlayer.this)
-
- // Sleep for a while.
- if (delay > 250) {
- delay = 250;
- }
- try {
- Thread.sleep(delay);
- } catch (InterruptedException e) {
- logger_.warning("Sequence.play() thread interrupted.");
- }
-
- synchronized (ScorePlayer.this) {
- currentTime_ += (delay / 1000.0);
- }
- } // while (true)
- } // run()
- }.start();
- }
-
- /**
- * This is a stupid hack because ListIterator doesn't have a peek method.
- */
- private static Event.Builder peek(ListIterator iterator) {
- Event.Builder event = iterator.next();
- iterator.previous();
- return event;
- }
-
- /**
- * Stops playback as soon as convenient. Doesn't block.
- */
- public synchronized void stopPlaying() {
- stop_ = true;
- }
-
- /**
- * Returns the number of seconds each measure of the song should take.
- */
- private synchronized double getSecondsPerMeasure() {
- return (beatsPerMeasure_ / beatsPerMinute_) * 60.0;
- }
-
- /**
- * Calls the onTimeUpdate() method of the listener.
- */
- private synchronized void onTimeUpdate() {
- listener_.onTimeUpdate(currentTime_ / getSecondsPerMeasure());
- }
-
- // The synthesizer to use for playing.
- private MidiListener synth_;
-
- // The tempo of the song.
- private double beatsPerMinute_;
-
- // The time signature of the score.
- private int beatsPerMeasure_;
-
- // The listener to notify of events.
- private ScorePlayerListener listener_;
-
- // Is the thread playing?
- private boolean playing_;
-
- // Should the thread stop?
- private boolean stop_;
-
- // The time of the current head of the playback, in seconds.
- private double currentTime_;
-
- // The sequence being played.
- private ListIterator starts_;
- private PriorityQueue ends_;
-
- private Logger logger_;
-}
diff --git a/core/src/com/levien/synthesizer/core/music/ScorePlayerListener.java b/core/src/com/levien/synthesizer/core/music/ScorePlayerListener.java
deleted file mode 100644
index ea6d61b..0000000
--- a/core/src/com/levien/synthesizer/core/music/ScorePlayerListener.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.music;
-
-/**
- * Listener for events from a ScorePlayer.
- * @see ScorePlayer
- */
-public interface ScorePlayerListener {
- /**
- * Called when playback starts.
- */
- void onStart();
-
- /**
- * Called every so often during playback.
- * @param time - time in measures from the start of the score.
- */
- void onTimeUpdate(double time);
-
- /**
- * Called when playback stops.
- */
- void onStop();
-}
diff --git a/core/src/com/levien/synthesizer/core/soundfont/Bag.java b/core/src/com/levien/synthesizer/core/soundfont/Bag.java
deleted file mode 100644
index c3671fd..0000000
--- a/core/src/com/levien/synthesizer/core/soundfont/Bag.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.soundfont;
-
-import java.io.IOException;
-
-import com.levien.synthesizer.core.wave.RiffInputStream;
-
-/**
- * A Bag is a structure particular to the SoundFont format that represents a list of generators and
- * modulators. It could be a "preset bag" or an "instrument bag", but it's basically the same.
- */
-public class Bag {
- /**
- * Reads one Bag from the given input stream.
- * @param input - An input stream where the next bytes represent a bag.
- */
- public Bag(RiffInputStream input) throws IOException {
- generatorStart_ = input.readWord();
- modulatorStart_ = input.readWord();
- generatorEnd_ = generatorStart_;
- modulatorEnd_ = modulatorStart_;
- }
-
- /**
- * @return The index of the first generator in this bag.
- */
- public int getGeneratorStart() {
- return generatorStart_;
- }
-
- /**
- * @return The index of the first modulator in this bag.
- */
- public int getModulatorStart() {
- return modulatorStart_;
- }
-
- /**
- * @return The index of the first generator after getGeneratorStart() *not* in this bag.
- */
- public int getGeneratorEnd() {
- return generatorEnd_;
- }
-
- /**
- * @return The index of the first modulator after getModulatorStart() *not* in this bag.
- */
- public int getModulatorEnd() {
- return modulatorEnd_;
- }
-
- /**
- * Sets the value to be returned by getGeneratorEnd().
- */
- public void setGeneratorEnd(int end) {
- generatorEnd_ = end;
- }
-
- /**
- * Sets the value to be returned by getModulatorEnd().
- */
- public void setModulatorEnd(int end) {
- modulatorEnd_ = end;
- }
-
- /**
- * Returns a user-readable string representing this bag.
- */
- public String toString() {
- return
- "Bag {\n" +
- " generator: [" + generatorStart_ + ", " + generatorEnd_ + ")\n" +
- " modulator: [" + modulatorStart_ + ", " + modulatorEnd_ + ")\n" +
- "}";
- }
-
- private int generatorStart_;
- private int modulatorStart_;
- private int generatorEnd_;
- private int modulatorEnd_;
-}
diff --git a/core/src/com/levien/synthesizer/core/soundfont/Generator.java b/core/src/com/levien/synthesizer/core/soundfont/Generator.java
deleted file mode 100644
index 6cc4793..0000000
--- a/core/src/com/levien/synthesizer/core/soundfont/Generator.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.soundfont;
-
-import java.io.IOException;
-
-import com.levien.synthesizer.core.wave.RiffInputStream;
-
-/**
- * A Generator is a SoundFont data structure that represents an "operator" and an "amount".
- */
-public class Generator {
- /**
- * Reads one generator from the given input.
- */
- public Generator(RiffInputStream input) throws IOException {
- operator_ = Operator.fromType(input.readWord());
- amount_ = input.readShort();
- }
-
- /**
- * @return The operator for this generator.
- */
- public Operator getOperator() {
- return operator_;
- }
-
- /**
- * @return The unprocessed argument associated with this generator.
- */
- public short getAmount() {
- return amount_;
- }
-
- /**
- * Returns a user-readable string representing this generator.
- */
- public String toString() {
- return
- "Generator {\n" +
- " operator: " + operator_.toString() + " (" + operator_.getType() + ")\n" +
- " amount: " + amount_ + "\n" +
- "}";
- }
-
- private Operator operator_;
- private short amount_;
-}
diff --git a/core/src/com/levien/synthesizer/core/soundfont/Instrument.java b/core/src/com/levien/synthesizer/core/soundfont/Instrument.java
deleted file mode 100644
index 57775a4..0000000
--- a/core/src/com/levien/synthesizer/core/soundfont/Instrument.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.soundfont;
-
-import java.io.IOException;
-import java.util.ArrayList;
-
-import com.levien.synthesizer.core.wave.RiffInputStream;
-
-/**
- * An instrument is a SoundFont data structure that consists of a set of zones. Each "zone" is
- * basically a flattened "bag" with a sample and a key range, etc.
- */
-public class Instrument {
- /**
- * Reads one instrument from the given input.
- */
- public Instrument(RiffInputStream input) throws IOException {
- name_ = input.readString(20);
- bagStart_ = input.readWord();
- bagEnd_ = bagStart_;
- zoneList_ = new ArrayList();
- }
-
- public String getName() {
- return name_;
- }
-
- public int getBagStart() {
- return bagStart_;
- }
-
- public int getBagEnd() {
- return bagEnd_;
- }
-
- public void setBagEnd(int end) {
- bagEnd_ = end;
- }
-
- public void addZone(Zone zone) {
- zoneList_.add(zone);
- }
-
- public ArrayList getZoneList() {
- return zoneList_;
- }
-
- /**
- * Returns a user-readable string representing this instrument.
- */
- public String toString() {
- return
- "Instrument {\n" +
- " name: \"" + name_ + "\"\n" +
- " bag index: [" + bagStart_ + ", " + bagEnd_ + ")\n" +
- "}";
- }
-
- private String name_;
- private int bagStart_;
- private int bagEnd_;
- private ArrayList zoneList_;
-}
diff --git a/core/src/com/levien/synthesizer/core/soundfont/Modulator.java b/core/src/com/levien/synthesizer/core/soundfont/Modulator.java
deleted file mode 100644
index 0d5811b..0000000
--- a/core/src/com/levien/synthesizer/core/soundfont/Modulator.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.soundfont;
-
-import java.io.IOException;
-
-import com.levien.synthesizer.core.wave.RiffInputStream;
-
-/**
- * A Modulator is a SoundFont data structure. They are read in by this library, but then ignored.
- */
-public class Modulator {
- public Modulator(RiffInputStream input) throws IOException {
- sourceOperator = new ModulatorSource(input.readWord());
- destinationOperator = input.readWord();
- amount = input.readShort();
- amountOperator = new ModulatorSource(input.readWord());
- transform = input.readWord();
- }
-
- public String toString() {
- return
- "Modulator {\n" +
- " source operator: \n" +
- sourceOperator + "\n" +
- " destination operator: " + destinationOperator + "\n" +
- " amount: " + amount + "\n" +
- " amount operator: \n" +
- amountOperator + "\n" +
- " transform: " + transform + "\n" +
- "}";
- }
-
- public ModulatorSource sourceOperator;
- public int destinationOperator;
- public short amount;
- public ModulatorSource amountOperator;
- public int transform;
-}
diff --git a/core/src/com/levien/synthesizer/core/soundfont/ModulatorSource.java b/core/src/com/levien/synthesizer/core/soundfont/ModulatorSource.java
deleted file mode 100644
index 12b694c..0000000
--- a/core/src/com/levien/synthesizer/core/soundfont/ModulatorSource.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.soundfont;
-
-/**
- * A ModulatorSource is a SoundFont data structure. They are read by this library and then ignored.
- */
-public class ModulatorSource {
- /**
- * Initializes the source from the given value.
- */
- public ModulatorSource(int value) {
- type_ = (byte)((0xFC00 & value) >> 10);
- polarity_ = ((value & 0x0200) != 0);
- direction_ = ((value & 0x0100) != 0);
- continuous_ = ((value & 0x0080) != 0);
- index_ = (byte)(0x007F & value);
- }
-
- public String toString() {
- return
- " ModulatorSource {\n" +
- " type: " + type_ + "\n" +
- " polarity: " + polarity_ + "\n" +
- " direction: " + direction_ + "\n" +
- " continuous: " + continuous_ + "\n" +
- " index: " + index_ + "\n" +
- " }";
- }
-
- private byte type_;
- public boolean polarity_;
- public boolean direction_;
- public boolean continuous_;
- public byte index_;
-}
diff --git a/core/src/com/levien/synthesizer/core/soundfont/Operator.java b/core/src/com/levien/synthesizer/core/soundfont/Operator.java
deleted file mode 100644
index 21d5c0e..0000000
--- a/core/src/com/levien/synthesizer/core/soundfont/Operator.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.soundfont;
-
-/**
- * An enumeration of all possible SoundFont Generator Operators.
- * Most of these are ignored.
- */
-public enum Operator {
- UNSUPPORTED(-1),
- START_ADDRS_OFFSET(0, false),
- END_ADDRS_OFFSET(1, false),
- STARTLOOP_ADDRS_OFFSET(2, false),
- ENDLOOP_ADDRS_OFFSET(3, false),
- START_ADDRS_COARSE_OFFSET(4, false),
- MOD_LFO_TO_PITCH(5),
- VIB_LFO_TO_PITCH(6),
- MOD_ENV_TO_PITCH(7),
- INITIAL_FILTER_FC(8),
- INITIAL_FILTER_Q(9),
- MOD_LFO_TO_FILTER_FC(10),
- MOD_ENV_TO_FILTER_FC(11),
- END_ADDRS_COARSE_OFFSET(12, false),
- MOD_LFO_TO_VOLUME(13),
- CHORUS_EFFECTS_SEND(15),
- REVERB_EFFECTS_SEND(16),
- PAN(17),
- DELAY_MOD_LFO(21),
- FREQ_MOD_LFO(22),
- DELAY_VIB_LFO(23),
- FREQ_VIB_LFO(24),
- DELAY_MOD_ENV(25),
- ATTACK_MOD_ENV(26),
- HOLD_MOD_ENV(27),
- DECAY_MOD_ENV(28),
- SUSTAIN_MOD_ENV(29),
- RELEASE_MOD_ENV(30),
- KEYNUM_TO_MOD_ENV_HOLD(31),
- KEYNUM_TO_MOD_ENV_DECAY(32),
- DELAY_VOL_ENV(33),
- ATTACK_VOL_ENV(34),
- HOLD_VOL_ENV(35),
- DECAY_VOL_ENV(36),
- SUSTAIN_VOL_ENV(37),
- RELEASE_VOL_END(38),
- KEYNUM_TO_VOL_ENV_HOLD(39),
- KEYNUM_TO_VOL_ENV_DECAY(40),
- INSTRUMENT(41, true, false),
- KEY_RANGE(43),
- VELOCITY_RANGE(44),
- STARTLOOP_ADDRS_COARSE_OFFSET(45, false),
- KEYNUM(46, false),
- VELOCITY(47, false),
- INITIAL_ATTENUATION(48),
- ENDLOOP_ADDRS_COARSE_OFFSET(50, false),
- COARSE_TUNE(51),
- FINE_TUNE(52),
- SAMPLE_ID(53, false),
- SAMPLE_MODES(54, false),
- SCALE_TUNING(56),
- EXCLUSIVE_CLASS(57, false),
- OVERRIDING_ROOT_KEY(58, false),
- END_OPER(60);
-
- /**
- * Creates a new enum value.
- * @param type - The enum value in the SoundFont format.
- * @param validForPreset - True if this operator would be valid in a preset zone.
- * @param validForInstrument - True if this operator would be valid in an instrument zone.
- */
- Operator(int type, boolean validForPreset, boolean validForInstrument) {
- type_ = type;
- validForPreset_ = validForPreset;
- validForInstrument_ = validForInstrument;
- }
-
- /**
- * Creates a new enum value that is valid for an instrument zone.
- * @param type - The enum value in the SoundFont format.
- * @param validForPreset - True if this operator would be valid in a preset zone.
- */
- Operator(int type, boolean validForPreset) {
- this(type, validForPreset, true);
- }
-
- /**
- * Creates a new enum value that is valid for a preset or instrument zone.
- * @param type - The enum value in the SoundFont format.
- */
- Operator(int type) {
- this(type, true);
- }
-
- /**
- * @return The SoundFont enum value for this operator.
- */
- public int getType() {
- return type_;
- }
-
- /**
- * @return True if this operator is valid in a preset zone.
- */
- public boolean isValidForPreset() {
- return validForPreset_;
- }
-
- /**
- * @return True if this operator is valid in an instrument zone.
- */
- public boolean isValidForInstrument() {
- return validForInstrument_;
- }
-
- /**
- * @return The operator corresponding to the given type.
- * @param type - The enum value in the SoundFont format.
- */
- public static Operator fromType(int type) {
- // TODO(klimt): Keep an index instead of linear search.
- for (Operator op : Operator.values()) {
- if (op.getType() == type) {
- return op;
- }
- }
- return UNSUPPORTED;
- }
-
- private final int type_;
- private final boolean validForPreset_;
- private final boolean validForInstrument_;
-}
diff --git a/core/src/com/levien/synthesizer/core/soundfont/Preset.java b/core/src/com/levien/synthesizer/core/soundfont/Preset.java
deleted file mode 100644
index 9dcaa7f..0000000
--- a/core/src/com/levien/synthesizer/core/soundfont/Preset.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.soundfont;
-
-import java.io.IOException;
-import java.util.ArrayList;
-
-import com.levien.synthesizer.core.wave.RiffInputStream;
-
-/**
- * A Preset is a SoundFont data structure that corresponds to a bunch of "preset zones" and a set
- * of instruments.
- */
-public class Preset {
- /**
- * Reads one Preset from the given input stream.
- */
- public Preset(RiffInputStream input) throws IOException {
- name_ = input.readString(20);
- preset_ = input.readWord();
- bank_ = input.readWord();
- bagStart_ = input.readWord();
- bagEnd_ = bagStart_;
- library_ = input.readDWord();
- genre_ = input.readDWord();
- morphology_ = input.readDWord();
- zoneList_ = new ArrayList();
- }
-
- public String getName() {
- return name_;
- }
-
- public int getBagStart() {
- return bagStart_;
- }
-
- public int getBagEnd() {
- return bagEnd_;
- }
-
- public void setBagEnd(int end) {
- bagEnd_ = end;
- }
-
- public void addZone(Zone zone) {
- zoneList_.add(zone);
- }
-
- public ArrayList getZoneList() {
- return zoneList_;
- }
-
- public String toString() {
- return
- "Preset {\n" +
- " name: \"" + name_ + "\"\n" +
- " preset: " + preset_ + "\n" +
- " bank: " + bank_ + "\n" +
- " bag index: [" + bagStart_ + ", " + bagEnd_ + ")\n" +
- "}";
- }
-
- private String name_;
- private int preset_;
- private int bank_;
-
- private int bagStart_;
- private int bagEnd_;
-
- private ArrayList zoneList_;
-
- @SuppressWarnings("unused")
- private long library_;
- @SuppressWarnings("unused")
- private long genre_;
- @SuppressWarnings("unused")
- private long morphology_;
-}
diff --git a/core/src/com/levien/synthesizer/core/soundfont/Sample.java b/core/src/com/levien/synthesizer/core/soundfont/Sample.java
deleted file mode 100644
index 5c9ada6..0000000
--- a/core/src/com/levien/synthesizer/core/soundfont/Sample.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.soundfont;
-
-import java.io.IOException;
-
-import com.levien.synthesizer.core.wave.RiffInputStream;
-
-/**
- * A Sample is a subset of sample data from a SoundFont file.
- */
-public class Sample {
- /**
- * Reads one SampleHeader from the given input stream.
- * @param input - A SoundFont input stream.
- * @param samples - All of the sample data from the SoundFont file.
- */
- public Sample(RiffInputStream input, double[] samples) throws IOException {
- name_ = input.readString(20);
- start_ = (int)input.readDWord();
- end_ = (int)input.readDWord();
- startLoop_ = (int)input.readDWord();
- endLoop_ = (int)input.readDWord();
- sampleRate_ = input.readDWord();
- originalKey_ = input.readByte();
- correction_ = input.readChar();
- sampleLink_ = input.readWord();
- sampleType_ = SampleLink.fromType(input.readWord());
- if (sampleType_.equals(SampleLink.UNKNOWN) &&
- !name_.equals("EOS")) {
- throw new IOException("Unsupported sample type.");
- }
- sample_ = samples;
- }
-
- /**
- * @return The index of the first sample in the sample.
- */
- public long getStart() {
- return start_;
- }
-
- /**
- * @return The index of one past the last sample in the sample.
- */
- public long getEnd() {
- return end_;
- }
-
- /**
- * @return The sample rate of the sample.
- */
- public long getRate() {
- return sampleRate_;
- }
-
- /**
- * @return The number of samples in the sample.
- */
- public int getCount() {
- return end_ - start_;
- }
-
- /**
- * Returns one sample from the, um, sample.
- * @param i - The index of the sample. Should be between getStart() and getEnd().
- */
- public double getSample(int i) {
- return sample_[i];
- }
-
- /**
- * Returns a human-readable description of the sample.
- */
- public String toString() {
- return
- "SampleHeader {\n" +
- " name: " + name_ + "\n" +
- " start: " + start_ + "\n" +
- " end: " + end_ + "\n" +
- " start loop: " + startLoop_ + "\n" +
- " end loop: " + endLoop_ + "\n" +
- " sample rate: " + sampleRate_ + "\n" +
- " original key: " + originalKey_ + "\n" +
- " correction: " + correction_ + "\n" +
- " sample link: " + sampleLink_ + "\n" +
- " sample type: " + sampleType_.toString() + " (" + sampleType_.getType() + ")\n" +
- "}";
- }
-
- // The info from the SampleHeader.
- private String name_;
- private int start_;
- private int end_;
- private int startLoop_;
- private int endLoop_;
- private long sampleRate_;
- private short originalKey_;
- private byte correction_;
- private int sampleLink_;
- private SampleLink sampleType_;
-
- // All of the actual sample data from the SoundFont file.
- private double[] sample_;
-}
diff --git a/core/src/com/levien/synthesizer/core/soundfont/SampleLink.java b/core/src/com/levien/synthesizer/core/soundfont/SampleLink.java
deleted file mode 100644
index df3c96a..0000000
--- a/core/src/com/levien/synthesizer/core/soundfont/SampleLink.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.soundfont;
-
-/**
- * SampleLink enum for the SoundFont format.
- */
-public enum SampleLink {
- UNKNOWN(-1),
- MONO_SAMPLE(1),
- RIGHT_SAMPLE(2),
- LEFT_SAMPLE(4),
- LINKED_SAMPLE(8),
- ROM_MONO_SAMPLE(0x8001),
- ROM_RIGHT_SAMPLE(0x8002),
- ROM_LEFT_SAMPLE(0x8004),
- ROM_LINKED_SAMPLE(0x8008);
-
- /**
- * Creates a new enum value for the given type.
- */
- SampleLink(int type) {
- type_ = type;
- }
-
- /**
- * @return The enum value from the SoundFont format.
- */
- public int getType() {
- return type_;
- }
-
- /**
- * @return The enum corresponding to the given SoundFont format value.
- */
- public static SampleLink fromType(int type) {
- for (SampleLink sl : SampleLink.values()) {
- if (sl.getType() == type) {
- return sl;
- }
- }
- return UNKNOWN;
- }
-
- private final int type_;
-}
diff --git a/core/src/com/levien/synthesizer/core/soundfont/SoundFontOscillator.java b/core/src/com/levien/synthesizer/core/soundfont/SoundFontOscillator.java
deleted file mode 100644
index 7f5165e..0000000
--- a/core/src/com/levien/synthesizer/core/soundfont/SoundFontOscillator.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.soundfont;
-
-import java.util.Arrays;
-import java.util.logging.Logger;
-
-import com.levien.synthesizer.core.model.Envelope;
-import com.levien.synthesizer.core.model.FrequencyProvider;
-import com.levien.synthesizer.core.model.SynthesisTime;
-import com.levien.synthesizer.core.model.oscillator.Oscillator;
-import com.levien.synthesizer.core.music.Note;
-import com.levien.synthesizer.core.soundfont.Zone.SampleMode;
-
-/**
- * An oscillator module that outputs a sample from a file.
- */
-public class SoundFontOscillator extends Oscillator implements Envelope {
- /**
- * Creates a new oscillator from a preset in a SoundFont file.
- * @param frequency - The frequency determines what key was pressed.
- * @parma preset - The SoundFont preset to get the sample data from.
- * @param sampleRateInHz - The sample rate of the output synthesizer.
- */
- public SoundFontOscillator(FrequencyProvider frequency,
- Preset preset,
- double sampleRateInHz) {
- super(frequency);
- logger_ = Logger.getLogger(getClass().getName());
- preset_ = preset;
- sampleRateInHz_ = sampleRateInHz;
-
- // Find the max sample length.
- maxSampleLength_ = 1;
- for (Zone pzone : preset_.getZoneList()) {
- Instrument instrument = pzone.getInstrument();
- if (instrument != null) {
- for (Zone izone : instrument.getZoneList()) {
- Sample sample = izone.getSample();
- int length = (int)Math.ceil((sampleRateInHz_ * izone.getCount()) / sample.getRate());
- if (length > maxSampleLength_) {
- maxSampleLength_ = length;
- }
- }
- }
- }
-
- currentSample_ = null;
- currentSampleIndex_ = 0;
-
- buffer_ = new double[maxSampleLength_];
- Arrays.fill(buffer_, 0.0);
- bufferIndex_ = 0;
- }
-
- /**
- * Gets one value from the synthesizer.
- */
- public synchronized double computeValue(SynthesisTime time) {
- // How many samples have passed?
- double deltaTime = time.getAbsoluteTime() - previousTime_;
- previousTime_ = time.getAbsoluteTime();
-
- // First, skip over however many samples we've passed in the buffer.
- int bufferSamples = (int)(deltaTime * sampleRateInHz_ + 0.5);
- // If everything in the buffer would be skipped, don't do extra work.
- if (bufferSamples > buffer_.length) {
- bufferSamples = buffer_.length;
- }
- // Clear all of the ones we've passed.
- for (int i = 0; i < bufferSamples; ++i) {
- buffer_[bufferIndex_++] = 0.0;
- if (bufferIndex_ >= buffer_.length) {
- bufferIndex_ = 0;
- }
- }
- double output = buffer_[bufferIndex_];
-
- // If the instrument has been retriggered, find the right sample.
- if (pressed_) {
- pressed_ = false;
- int key = Note.getKeyforLog12TET(frequency_.getLogFrequency(time));
- int velocity = 255;
- initSample(key, velocity);
- } else {
- if (currentSample_ != null) {
- // Advance by deltaTime in the current sample.
- currentSampleIndex_ += deltaTime * currentSample_.getSample().getRate();
- if (currentSample_.getSampleMode() == SampleMode.NO_LOOP) {
- if (currentSampleIndex_ > currentSample_.getEnd()) {
- // We're off the end of the sample.
- currentSample_ = null;
- }
- } else {
- if (currentSampleIndex_ >= currentSample_.getEndLoop()) {
- double distanceFromLoopStart = currentSampleIndex_ - currentSample_.getStartLoop();
- double loopLength = currentSample_.getEndLoop() - currentSample_.getStartLoop();
- currentSampleIndex_ =
- currentSample_.getStartLoop() + (distanceFromLoopStart % loopLength);
- }
- }
- }
- }
-
- // Okay, now get the new data from the current sample.
- if (currentSample_ != null) {
- int firstSample = (int)currentSampleIndex_;
- double weight = 1.0 - (currentSampleIndex_ - firstSample);
- if (weight == 1.0) {
- output += currentSample_.getSample().getSample(firstSample);
- } else {
- output +=
- weight * currentSample_.getSample().getSample(firstSample) +
- (1.0 - weight) * currentSample_.getSample().getSample(firstSample + 1);
- }
- }
-
- return output;
- }
-
- /**
- * Initializes the "current sample" based on the given key and velocity.
- */
- private synchronized void initSample(int key, int velocity) {
- // Find any sample in this preset that can handle the given key and velocity.
- currentSample_ = null;
- for (Zone pzone : preset_.getZoneList()) {
- Instrument instrument = pzone.getInstrument();
- if (instrument != null) {
- for (Zone izone : instrument.getZoneList()) {
- if (izone.inKeyRange(key) &&
- izone.inVelocityRange(velocity) &&
- izone.getSample() != null) {
- currentSample_ = izone;
- currentSampleIndex_ = currentSample_.getStart();
- return;
- }
- }
- }
- }
- }
-
- /**
- * Trigger this oscillator to start outputting from the sample.
- */
- public synchronized void turnOn(boolean retriggerIfOn) {
- pressed_ = true;
- }
-
- /**
- * Turns off this oscillator from getting data from the current sample.
- * If this sample supports it, then the rest of the current sample is copied to the output buffer
- * before the current sample is cleared.
- */
- public synchronized void turnOff() {
- if (currentSample_ != null) {
- // Copy in the rest of the current sample.
- int bufferIndex = bufferIndex_;
- while (currentSampleIndex_ <= currentSample_.getEnd()) {
- int firstSample = (int)currentSampleIndex_;
- double weight = 1.0 - (currentSampleIndex_ - firstSample);
- if (weight == 1.0) {
- buffer_[bufferIndex] += currentSample_.getSample().getSample(firstSample);
- } else {
- buffer_[bufferIndex] +=
- weight * currentSample_.getSample().getSample(firstSample) +
- (1.0 - weight) * currentSample_.getSample().getSample(firstSample + 1);
- }
- bufferIndex = (bufferIndex + 1) % buffer_.length;
- currentSampleIndex_ += (currentSample_.getSample().getRate() / sampleRateInHz_);
- }
- }
- currentSample_ = null;
- }
-
- @SuppressWarnings("unused")
- private Logger logger_;
-
- // The preset to get samples from.
- private Preset preset_;
-
- // The current sample being played, and where in the sample we are currently at in the output.
- private Zone currentSample_;
- private double currentSampleIndex_;
-
- // A buffer of data that has been queued up and should be played in the future. This handles the
- // case of releasing the key and then pressing it again at a different value.
- private double[] buffer_;
- private int bufferIndex_;
-
- // True if the oscillator has been triggered, but the sample hasn't been loaded yet.
- private boolean pressed_;
-
- // The previous time the oscillator was polled for its value.
- private double previousTime_;
-
- // The maximum length of any sample in this preset, converted to the output sample rate.
- private int maxSampleLength_;
-
- // The sample rate of the output synthesizer.
- private double sampleRateInHz_;
-}
diff --git a/core/src/com/levien/synthesizer/core/soundfont/SoundFontReader.java b/core/src/com/levien/synthesizer/core/soundfont/SoundFontReader.java
deleted file mode 100644
index f482da6..0000000
--- a/core/src/com/levien/synthesizer/core/soundfont/SoundFontReader.java
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.soundfont;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Logger;
-
-//import com.levien.synthesizer.core.model.sample.Proto;
-import com.levien.synthesizer.core.wave.RiffInputStream;
-
-/**
- * Reads a SoundFont file from a stream and provides access its data.
- */
-public class SoundFontReader {
- /**
- * Reads the .sf2 file from a stream and stores the data in a buffer.
- * @param input - the stream to read from.
- * @throws IOExpection - on a malformed or unsupported file format.
- */
- public SoundFontReader(InputStream in) throws IOException {
- Logger logger = Logger.getLogger(getClass().getName());
- logger.info("Loading SoundFont file.");
-
- RiffInputStream input = new RiffInputStream(in);
-
- input.checkBytes("RIFF");
- long riffSize = input.readDWord();
- long riffRemaining = riffSize;
-
- input.checkBytes("sfbk");
- riffRemaining -= 4;
-
- // All of the sample data, scaled from -1 to 1.
- double[] samples = null;
-
- while (riffRemaining > 0) {
- input.checkBytes("LIST");
- long listSize = input.readDWord();
- riffRemaining -= 8;
- riffRemaining -= listSize;
- String chunk = input.readString(4);
- long listRemaining = listSize;
- listRemaining -= 4;
- if (chunk.equals("INFO")) {
- // Mostly worthless info headers.
- while (listRemaining > 0) {
- String subchunk = input.readString(4);
- int subchunkSize = (int)input.readDWord();
- listRemaining -= 8;
- listRemaining -= subchunkSize;
- if (subchunk.equals("ifil")) {
- if (subchunkSize != 4) {
- throw new IOException("ifil size != 4.");
- }
- majorVersion_ = input.readWord();
- minorVersion_ = input.readWord();
- } else if (subchunk.equals("isng")) {
- engine_ = input.readString(subchunkSize);
- } else if (subchunk.equals("INAM")) {
- name_ = input.readString(subchunkSize);
- } else if (subchunk.equals("irom")) {
- rom_ = input.readString(subchunkSize);
- } else if (subchunk.equals("iver")) {
- if (subchunkSize != 4) {
- throw new IOException("iver size != 4.");
- }
- romMajorVersion_ = input.readWord();
- romMinorVersion_ = input.readWord();
- } else if (subchunk.equals("ICRD")) {
- creationDate_ = input.readString(subchunkSize);
- } else if (subchunk.equals("IENG")) {
- engineer_ = input.readString(subchunkSize);
- } else if (subchunk.equals("IPRD")) {
- product_ = input.readString(subchunkSize);
- } else if (subchunk.equals("ICOP")) {
- copyright_ = input.readString(subchunkSize);
- } else if (subchunk.equals("ICMT")) {
- comment_ = input.readString(subchunkSize);
- } else if (subchunk.equals("ISFT")) {
- software_ = input.readString(subchunkSize);
- } else {
- logger.info("Skipping unknown INFO subchunk type " + subchunk + ".");
- input.skipBytes(subchunkSize);
- }
- }
- System.out.println("Read SoundFont INFO: \n" + this.toString());
- } else if (chunk.equals("sdta")) {
- // The actual sample data.
- while (listRemaining > 0) {
- String subchunk = input.readString(4);
- long subchunkSize = input.readDWord();
- listRemaining -= 8;
- listRemaining -= subchunkSize;
- if (subchunk.equals("smpl")) {
- int words = (int)(subchunkSize / 2);
- logger.info("Reading " + words + " samples.");
- samples = new double[words];
- for (int i = 0; i < words; ++i) {
- samples[i] = input.readShort() / 32768.0;
- }
- } else {
- logger.info("Skipping unknown sdta subchunk type " + subchunk + ".");
- input.skipBytes(subchunkSize);
- }
- }
- } else if (chunk.equals("pdta")) {
- // This is the so-called HYDRA data structure, with 9 parts.
-
- ArrayList presetBagList = new ArrayList();
- ArrayList presetModulatorList = new ArrayList();
- ArrayList presetGeneratorList = new ArrayList();
- ArrayList instrumentList = new ArrayList();
- ArrayList instrumentBagList = new ArrayList();
- ArrayList instrumentModulatorList = new ArrayList();
- ArrayList instrumentGeneratorList = new ArrayList();
- ArrayList sampleHeaderList = new ArrayList();
-
- // Preset data is the metadata about the samples.
- while (listRemaining > 0) {
- String subchunk = input.readString(4);
- long subchunkSize = input.readDWord();
- listRemaining -= 8;
- listRemaining -= subchunkSize;
- byte[] subchunkData = input.readBytes((int)subchunkSize);
- ByteArrayInputStream subchunkInput = new ByteArrayInputStream(subchunkData);
- if (subchunk.equals("phdr")) {
- Preset previous = null;
- while (subchunkInput.available() > 0) {
- Preset preset = new Preset(new RiffInputStream(subchunkInput));
- logger.info("Found preset: " + preset.getName());
- if (previous != null) {
- previous.setBagEnd(preset.getBagStart());
- presets_.add(previous);
- }
- previous = preset;
- }
- } else if (subchunk.equals("pbag")) {
- Bag previous = null;
- while (subchunkInput.available() > 0) {
- Bag presetBag = new Bag(new RiffInputStream(subchunkInput));
- if (previous != null) {
- previous.setGeneratorEnd(presetBag.getGeneratorStart());
- previous.setModulatorEnd(presetBag.getModulatorStart());
- presetBagList.add(previous);
- }
- previous = presetBag;
- }
- } else if (subchunk.equals("pmod")) {
- while (subchunkInput.available() > 0) {
- Modulator presetModulator = new Modulator(new RiffInputStream(subchunkInput));
- if (subchunkInput.available() > 0) {
- presetModulatorList.add(presetModulator);
- }
- }
- } else if (subchunk.equals("pgen")) {
- while (subchunkInput.available() > 0) {
- Generator generator = new Generator(new RiffInputStream(subchunkInput));
- if (subchunkInput.available() > 0) {
- presetGeneratorList.add(generator);
- }
- }
- } else if (subchunk.equals("inst")) {
- Instrument previous = null;
- while (subchunkInput.available() > 0) {
- Instrument instrument = new Instrument(new RiffInputStream(subchunkInput));
- logger.info("Found instrument: " + instrument.getName());
- if (previous != null) {
- previous.setBagEnd(instrument.getBagStart());
- instrumentList.add(previous);
- }
- previous = instrument;
- }
- } else if (subchunk.equals("ibag")) {
- Bag previous = null;
- while (subchunkInput.available() > 0) {
- Bag instrumentBag = new Bag(new RiffInputStream(subchunkInput));
- if (previous != null) {
- previous.setGeneratorEnd(instrumentBag.getGeneratorStart());
- previous.setModulatorEnd(instrumentBag.getModulatorStart());
- instrumentBagList.add(previous);
- }
- previous = instrumentBag;
- }
- } else if (subchunk.equals("imod")) {
- while (subchunkInput.available() > 0) {
- Modulator instrumentModulator = new Modulator(new RiffInputStream(subchunkInput));
- if (subchunkInput.available() > 0) {
- instrumentModulatorList.add(instrumentModulator);
- }
- }
- } else if (subchunk.equals("igen")) {
- while (subchunkInput.available() > 0) {
- Generator generator = new Generator(new RiffInputStream(subchunkInput));
- if (subchunkInput.available() > 0) {
- instrumentGeneratorList.add(generator);
- }
- }
- } else if (subchunk.equals("shdr")) {
- while (subchunkInput.available() > 0) {
- Sample sampleHeader = new Sample(new RiffInputStream(subchunkInput),
- samples);
- if (subchunkInput.available() > 0) {
- sampleHeaderList.add(sampleHeader);
- }
- }
- } else {
- logger.info("Skipping unknown pdta subchunk type " + subchunk + ".");
- }
- }
-
- // Now that we've read in the HYDRA, we have to backtrack through it to convert the _bags_
- // to _zones_.
-
- for (Preset preset : presets_) {
- // There might be a "global" zone for the preset that applies to all the other zones.
- Zone globalZone = null;
- for (int bag = preset.getBagStart(); bag < preset.getBagEnd(); ++bag) {
- // Start with the global zone, if it exists.
- Zone zone = (globalZone != null) ? globalZone.copy() : new Zone();
- for (int gen = presetBagList.get(bag).getGeneratorStart();
- gen < presetBagList.get(bag).getGeneratorEnd();
- ++gen) {
- zone.addPresetGenerator(presetGeneratorList.get(gen), instrumentList);
- }
- for (int mod = presetBagList.get(bag).getModulatorStart();
- mod < presetBagList.get(bag).getModulatorEnd();
- ++mod) {
- zone.addModulator(presetModulatorList.get(mod));
- }
- // This might be the global zone for the preset.
- if (zone.getInstrument() == null) {
- if (globalZone == null) {
- // It is the global zone, so set it.
- globalZone = zone;
- }
- // Any zone missing an instrument is either the global zone or should be ignored.
- continue;
- }
- // Okay, it's not the global zone.
- preset.addZone(zone);
- }
- }
-
- for (Instrument instrument : instrumentList) {
- // There might be a "global" zone for the preset that applies to all the other zones.
- Zone globalZone = null;
- for (int bag = instrument.getBagStart(); bag < instrument.getBagEnd(); ++bag) {
- // Start with the global zone, if it exists.
- Zone zone = (globalZone != null) ? globalZone.copy() : new Zone();
- for (int gen = instrumentBagList.get(bag).getGeneratorStart();
- gen < instrumentBagList.get(bag).getGeneratorEnd();
- ++gen) {
- zone.addInstrumentGenerator(instrumentGeneratorList.get(gen), sampleHeaderList);
- }
- for (int mod = instrumentBagList.get(bag).getModulatorStart();
- mod < instrumentBagList.get(bag).getModulatorEnd();
- ++mod) {
- zone.addModulator(instrumentModulatorList.get(mod));
- }
- // This might be the global zone for the preset.
- if (zone.getSample() == null) {
- if (globalZone == null) {
- // It is the global zone, so set it.
- globalZone = zone;
- }
- // Any zone missing an instrument is either the global zone or should be ignored.
- continue;
- }
- // Okay, it's not the global zone.
- instrument.addZone(zone);
- }
- }
-
- // TODO(klimt): So, actually some of the generator values for an instrument should be added
- // to the generator values for the preset zone it's in, but an instrument could be in
- // multiple different preset zones, so there's no way to store that here. So I need to make
- // a function to add two zones, and call it whenever the instrument zone is used. Grrr.
- } else {
- logger.info("Skipping unknown sfbk LIST type " + chunk + ".");
- input.skipBytes(listRemaining);
- }
- }
- input.close();
- }
-
- public List getPresets() {
- return presets_;
- }
-
- public String toString() {
- return
- "version: " + majorVersion_ + "." + minorVersion_ + "\n" +
- "engine: " + engine_ + "\n" +
- "name: " + name_ + "\n" +
- "rom: " + rom_ + "\n" +
- "rom version: " + romMajorVersion_ + "." + romMinorVersion_ + "\n" +
- "created: " + creationDate_ + "\n" +
- "engineer: " + engineer_ + "\n" +
- "product: " + product_ + "\n" +
- "copyright: " + copyright_ + "\n" +
- "comment: " + comment_ + "\n" +
- "software: " + software_ + "\n";
- }
-
- private int majorVersion_;
- private int minorVersion_;
- private String engine_;
- private String name_;
- private String rom_;
- private int romMajorVersion_;
- private int romMinorVersion_;
- private String creationDate_;
- private String engineer_;
- private String product_;
- private String copyright_;
- private String comment_;
- private String software_;
- private ArrayList presets_ = new ArrayList();
-}
diff --git a/core/src/com/levien/synthesizer/core/soundfont/Zone.java b/core/src/com/levien/synthesizer/core/soundfont/Zone.java
deleted file mode 100644
index db077af..0000000
--- a/core/src/com/levien/synthesizer/core/soundfont/Zone.java
+++ /dev/null
@@ -1,530 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.soundfont;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Logger;
-
-/**
- * A zone is like a flattened bag that contains any of the settings that could be in a bag.
- */
-@SuppressWarnings("unused")
-public class Zone {
- /**
- * Creates a new Zone that's empty.
- */
- public Zone() {
- logger_ = Logger.getLogger(getClass().getName());
- modulatorList_ = new ArrayList();
- }
-
- /**
- * Copies all of the values from another zone into this one.
- */
- public void CopyFrom(Zone other) {
- instrument_ = other.instrument_;
- sample_ = other.sample_;
- startAddrsOffset_ = other.startAddrsOffset_;
- endAddrsOffset_ = other.endAddrsOffset_;
- startloopAddrsOffset_ = other.startloopAddrsOffset_;
- endloopAddrsOffset_ = other.endloopAddrsOffset_;
- startAddrsCoarseOffset_ = other.startAddrsCoarseOffset_;
- endAddrsCoarseOffset_ = other.endAddrsCoarseOffset_;
- startloopAddrsCoarseOffset_ = other.startloopAddrsCoarseOffset_;
- endloopAddrsCoarseOffset_ = other.endloopAddrsCoarseOffset_;
- modLfoToPitch_ = other.modLfoToPitch_;
- vibLfoToPitch_ = other.vibLfoToPitch_;
- modEnvToPitch_ = other.modEnvToPitch_;
- initialFilterFc_ = other.initialFilterFc_;
- initialFilterQ_ = other.initialFilterQ_;
- modLfoToFilterFc_ = other.modLfoToFilterFc_;
- modEnvToFilterFc_ = other.modEnvToFilterFc_;
- modLfoToVolume_ = other.modLfoToVolume_;
- chorusEffectsSend_ = other.chorusEffectsSend_;
- reverbEffectsSend_ = other.reverbEffectsSend_;
- pan_ = other.pan_;
- delayModLFO_ = other.delayModLFO_;
- freqModLFO_ = other.freqModLFO_;
- delayVibLFO_ = other.delayVibLFO_;
- freqVibLFO_ = other.freqVibLFO_;
- delayModEnv_ = other.delayModEnv_;
- attackModEnv_ = other.attackModEnv_;
- holdModEnv_ = other.holdModEnv_;
- decayModEnv_ = other.decayModEnv_;
- sustainModEnv_ = other.sustainModEnv_;
- releaseModEnv_ = other.releaseModEnv_;
- keynumToModEnvHold_ = other.keynumToModEnvHold_;
- keynumToModEnvDecay_ = other.keynumToModEnvDecay_;
- delayVolEnv_ = other.delayVolEnv_;
- attackVolEnv_ = other.attackVolEnv_;
- holdVolEnv_ = other.holdVolEnv_;
- decayVolEnv_ = other.decayVolEnv_;
- sustainVolEnv_ = other.sustainVolEnv_;
- releaseVolEnv_ = other.releaseVolEnv_;
- keynumToVolEnvHold_ = other.keynumToVolEnvHold_;
- keynumToVolEnvDecay_ = other.keynumToVolEnvDecay_;
- minKey_ = other.minKey_;
- maxKey_ = other.maxKey_;
- minVelocity_ = other.minVelocity_;
- maxVelocity_ = other.maxVelocity_;
- keynum_ = other.keynum_;
- velocity_ = other.velocity_;
- initialAttenuation_ = other.initialAttenuation_;
- coarseTune_ = other.coarseTune_;
- fineTune_ = other.fineTune_;
- sampleMode_ = other.sampleMode_;
- scaleTuning_ = other.scaleTuning_;
- exclusiveClass_ = other.exclusiveClass_;
- overridingRootKey_ = other.overridingRootKey_;
- modulatorList_ = new ArrayList(other.modulatorList_);
- }
-
- /**
- * @return A new Zone equivalent to this one.
- */
- public Zone copy() {
- Zone other = new Zone();
- other.CopyFrom(this);
- return other;
- }
-
- /**
- * @return The input converted from cents to octaves.
- */
- private static double convertCentsToOctaves(double value) {
- return value / 1200.0;
- }
-
- /**
- * @return The input converted from cents to seconds.
- */
- private static double convertCentsToSeconds(double value) {
- return Math.pow(2.0, convertCentsToOctaves(value));
- }
-
- /**
- * Adds a preset generator to this Zone.
- * @param generator - The generator to add.
- * @param instruments - The list of all instruments in this SoundFont file.
- */
- public void addPresetGenerator(Generator generator,
- List instruments) {
- if (!generator.getOperator().isValidForPreset()) {
- throw new IllegalArgumentException("Invalid operator for preset: " +
- generator.getOperator() + ".");
- }
- addGenerator(generator, instruments, null);
- }
-
- /**
- * Adds an instrument generator to this Zone.
- * @param generator - The generator to add.
- * @param samples - The list of all samples in this SoundFont file.
- */
- public void addInstrumentGenerator(Generator generator,
- List samples) {
- if (!generator.getOperator().isValidForInstrument()) {
- throw new IllegalArgumentException("Invalid operator for instrument: " +
- generator.getOperator() + ".");
- }
- addGenerator(generator, null, samples);
- }
-
- /**
- * Internal method to add a generator of either type.
- */
- protected void addGenerator(Generator generator,
- List instruments,
- List samples) {
- short amount = generator.getAmount();
- //
- // This ridiculous switch statement takes the given operator and decodes its argument into the
- // right values in the Zone.
- //
- switch (generator.getOperator()) {
- case UNSUPPORTED: {
- break;
- }
- case START_ADDRS_OFFSET: {
- startAddrsOffset_ = amount; break;
- }
- case END_ADDRS_OFFSET: {
- endAddrsOffset_ = amount; break;
- }
- case STARTLOOP_ADDRS_OFFSET: {
- startloopAddrsOffset_ = amount; break;
- }
- case ENDLOOP_ADDRS_OFFSET: {
- endloopAddrsOffset_ = amount; break;
- }
- case START_ADDRS_COARSE_OFFSET: {
- startAddrsCoarseOffset_ = amount * 32768; break;
- }
- case MOD_LFO_TO_PITCH: {
- modLfoToPitch_ = convertCentsToOctaves(amount); break;
- }
- case VIB_LFO_TO_PITCH: {
- vibLfoToPitch_ = convertCentsToOctaves(amount); break;
- }
- case MOD_ENV_TO_PITCH: {
- modEnvToPitch_ = convertCentsToOctaves(amount); break;
- }
- case INITIAL_FILTER_FC: {
- initialFilterFc_ = convertCentsToOctaves(amount); break;
- }
- case INITIAL_FILTER_Q: {
- initialFilterQ_ = amount; break;
- }
- case MOD_LFO_TO_FILTER_FC: {
- modLfoToFilterFc_ = convertCentsToOctaves(amount); break;
- }
- case MOD_ENV_TO_FILTER_FC: {
- modEnvToFilterFc_ = convertCentsToOctaves(amount); break;
- }
- case END_ADDRS_COARSE_OFFSET: {
- endAddrsCoarseOffset_ = amount * 32768; break;
- }
- case MOD_LFO_TO_VOLUME: {
- modLfoToVolume_ = amount; break;
- }
- case CHORUS_EFFECTS_SEND: {
- chorusEffectsSend_ = amount / 1000.0; break;
- }
- case REVERB_EFFECTS_SEND: {
- reverbEffectsSend_ = amount / 1000.0; break;
- }
- case PAN: {
- pan_ = amount / 1000.0; break;
- }
- case DELAY_MOD_LFO: {
- delayModLFO_ = convertCentsToSeconds(amount); break;
- }
- case FREQ_MOD_LFO: {
- freqModLFO_ = convertCentsToOctaves(amount); break;
- }
- case DELAY_VIB_LFO: {
- delayVibLFO_ = convertCentsToSeconds(amount); break;
- }
- case FREQ_VIB_LFO: {
- freqVibLFO_ = convertCentsToOctaves(amount); break;
- }
- case DELAY_MOD_ENV: {
- delayModEnv_ = convertCentsToSeconds(amount); break;
- }
- case ATTACK_MOD_ENV: {
- attackModEnv_ = convertCentsToSeconds(amount); break;
- }
- case HOLD_MOD_ENV: {
- holdModEnv_ = convertCentsToSeconds(amount); break;
- }
- case DECAY_MOD_ENV: {
- decayModEnv_ = convertCentsToSeconds(amount); break;
- }
- case SUSTAIN_MOD_ENV: {
- sustainModEnv_ = 1.0 - (amount / -1000.0); break;
- }
- case RELEASE_MOD_ENV: {
- releaseModEnv_ = convertCentsToSeconds(amount); break;
- }
- case KEYNUM_TO_MOD_ENV_HOLD: {
- keynumToModEnvHold_ = convertCentsToSeconds(amount); break;
- }
- case KEYNUM_TO_MOD_ENV_DECAY: {
- keynumToModEnvDecay_ = convertCentsToSeconds(amount); break;
- }
- case DELAY_VOL_ENV: {
- delayVolEnv_ = convertCentsToSeconds(amount); break;
- }
- case ATTACK_VOL_ENV: {
- attackVolEnv_ = convertCentsToSeconds(amount); break;
- }
- case HOLD_VOL_ENV: {
- holdVolEnv_ = convertCentsToSeconds(amount); break;
- }
- case DECAY_VOL_ENV: {
- decayVolEnv_ = convertCentsToSeconds(amount); break;
- }
- case SUSTAIN_VOL_ENV: {
- sustainVolEnv_ = 1.0 - (amount / -1000.0); break;
- }
- case RELEASE_VOL_END: {
- releaseVolEnv_ = convertCentsToSeconds(amount); break;
- }
- case KEYNUM_TO_VOL_ENV_HOLD: {
- keynumToVolEnvHold_ = convertCentsToSeconds(amount); break;
- }
- case KEYNUM_TO_VOL_ENV_DECAY: {
- keynumToVolEnvDecay_ = convertCentsToSeconds(amount); break;
- }
- case INSTRUMENT: {
- instrument_ = instruments.get(((int)amount) & 0xFFFF); break;
- }
- case KEY_RANGE: {
- minKey_ = amount & 0xFF;
- maxKey_ = (amount >> 8) & 0xFF;
- break;
- }
- case VELOCITY_RANGE: {
- minVelocity_ = amount & 0xFF;
- maxVelocity_ = (amount >> 8) & 0xFF;
- break;
- }
- case STARTLOOP_ADDRS_COARSE_OFFSET: {
- startloopAddrsCoarseOffset_ = amount * 32768; break;
- }
- case KEYNUM: {
- keynum_ = amount & 0xFF; break;
- }
- case VELOCITY: {
- velocity_ = amount & 0xFF; break;
- }
- case INITIAL_ATTENUATION: {
- initialAttenuation_ = amount; break;
- }
- case ENDLOOP_ADDRS_COARSE_OFFSET: {
- endloopAddrsCoarseOffset_ = amount * 32768; break;
- }
- case COARSE_TUNE: {
- coarseTune_ = amount / 12.0; break;
- }
- case FINE_TUNE: {
- fineTune_ = convertCentsToOctaves(amount); break;
- }
- case SAMPLE_ID: {
- sample_ = samples.get(((int)amount) & 0xFFFF); break;
- }
- case SAMPLE_MODES: {
- switch (amount & 0x03) {
- case 0: sampleMode_ = SampleMode.NO_LOOP; break;
- case 1: sampleMode_ = SampleMode.LOOP_CONTINUOUSLY; break;
- case 2: sampleMode_ = SampleMode.NO_LOOP; break;
- case 3: sampleMode_ = SampleMode.LOOP_CONTINUOUSLY_THEN_FINISH; break;
- }
- break;
- }
- case SCALE_TUNING: {
- scaleTuning_ = convertCentsToOctaves(amount); break;
- }
- case EXCLUSIVE_CLASS: {
- exclusiveClass_ = amount & 0xFF; break;
- }
- case OVERRIDING_ROOT_KEY: {
- overridingRootKey_ = amount & 0xFF; break;
- }
- case END_OPER: {
- break;
- }
- }
- }
-
- /**
- * Adds a modulator the zone.
- */
- public void addModulator(Modulator modulator) {
- modulatorList_.add(modulator);
- }
-
- /**
- * @return the index of the first sample in this instrument zone.
- * Adjusts based on the generator settings.
- */
- public long getStart() {
- long start = startAddrsOffset_ + startAddrsCoarseOffset_;
- if (sample_ != null) {
- start += sample_.getStart();
- }
- return start;
- }
-
- /**
- * @return the index one after the last sample in this instrument zone.
- * Adjusts based on the generator settings.
- */
- public long getEnd() {
- long end = endAddrsOffset_ + endAddrsCoarseOffset_;
- if (sample_ != null) {
- end += sample_.getEnd();
- }
- return end;
- }
-
- /**
- * @return the number of samples in this instrument zone.
- * Adjusts based on the generator settings.
- */
- public long getCount() {
- return getEnd() - getStart();
- }
-
- /**
- * @return the index of the first sample in this instrument zone's loop subset.
- * Adjusts based on the generator settings.
- */
- public long getStartLoop() {
- long startloop = startloopAddrsOffset_ + startloopAddrsCoarseOffset_;
- if (sample_ != null) {
- startloop += sample_.getStart();
- }
- return startloop;
- }
-
- /**
- * @return the index one after the last sample in this instrument zone's loop subset.
- * Adjusts based on the generator settings.
- */
- public long getEndLoop() {
- long endloop = endloopAddrsOffset_ + endloopAddrsCoarseOffset_;
- if (sample_ != null) {
- endloop += sample_.getEnd();
- }
- return endloop;
- }
-
- /**
- * @return The instrument associated with this preset zone.
- */
- public Instrument getInstrument() {
- return instrument_;
- }
-
- /**
- * @return True if this instrument zone can handle the given key.
- */
- public boolean inKeyRange(int key) {
- return ((minKey_ < 0 || key >= minKey_) &&
- (maxKey_ < 0 || key <= maxKey_));
- }
-
- /**
- * @return True if this instrument zone can handle the given velocity.
- */
- public boolean inVelocityRange(int velocity) {
- return ((minVelocity_ < 0 || velocity >= minVelocity_) &&
- (maxVelocity_ < 0 || velocity <= maxVelocity_));
- }
-
- /**
- * @return The sample associated with this instrument zone.
- */
- public Sample getSample() {
- return sample_;
- }
-
- /**
- * @return The sample mode for this instrument zone.
- */
- public SampleMode getSampleMode() {
- return sampleMode_;
- }
-
- private Logger logger_;
-
- //
- // The various settings for a zone, according to the SoundFont 2.1 format specification.
- // Most of these are ignored in this synthesizer implementation, but some are not.
- //
-
- private Instrument instrument_ = null; // Set for a preset zone.
- private Sample sample_ = null; // Set for an instrument zone.
-
- // All in samples.
- private int startAddrsOffset_ = 0;
- private int endAddrsOffset_ = 0;
- private int startloopAddrsOffset_ = 0;
- private int endloopAddrsOffset_ = 0;
- private int startAddrsCoarseOffset_ = 0;
- private int endAddrsCoarseOffset_ = 0;
- private int startloopAddrsCoarseOffset_ = 0;
- private int endloopAddrsCoarseOffset_ = 0;
-
- // All in log Hz.
- private double modLfoToPitch_ = 0;
- private double vibLfoToPitch_ = 0;
- private double modEnvToPitch_ = 0;
-
- private double initialFilterFc_ = convertCentsToOctaves(13500); // in log Hz.
- private int initialFilterQ_ = 0; // in centibels.
- private double modLfoToFilterFc_ = 0; // in log Hz.
- private double modEnvToFilterFc_ = 0; // in log Hz.
-
- private int modLfoToVolume_ = 0; // in centibels.
-
- // All are percentages.
- private double chorusEffectsSend_ = 0.0;
- private double reverbEffectsSend_ = 0.0;
- private double pan_ = 0.0;
-
- private double delayModLFO_ = convertCentsToSeconds(-12000); // in seconds.
- private double freqModLFO_ = 0; // in log Hz.
- private double delayVibLFO_ = convertCentsToSeconds(-12000); // in seconds.
- private double freqVibLFO_ = 0; // in log Hz.
-
- // All in seconds, except sustain.
- private double delayModEnv_ = convertCentsToSeconds(-12000);
- private double attackModEnv_ = convertCentsToSeconds(-12000);
- private double holdModEnv_ = convertCentsToSeconds(-12000);
- private double decayModEnv_ = convertCentsToSeconds(-12000);
- private double sustainModEnv_ = 0; // percentage.
- private double releaseModEnv_ = convertCentsToSeconds(-12000);
-
- // All in seconds per key.
- private double keynumToModEnvHold_ = 0;
- private double keynumToModEnvDecay_ = 0;
-
- // All in seconds, except sustain.
- private double delayVolEnv_ = convertCentsToSeconds(-12000);
- private double attackVolEnv_ = convertCentsToSeconds(-12000);
- private double holdVolEnv_ = convertCentsToSeconds(-12000);
- private double decayVolEnv_ = convertCentsToSeconds(-12000);
- private double sustainVolEnv_ = 0; // percentage.
- private double releaseVolEnv_ = convertCentsToSeconds(-12000);
-
- // All in seconds per key.
- private double keynumToVolEnvHold_ = 0;
- private double keynumToVolEnvDecay_ = 0;
-
- // These are midi values in the range [0, 127]. -1 means unset.
- private int minKey_ = -1;
- private int maxKey_ = -1;
- private int minVelocity_ = -1;
- private int maxVelocity_ = -1;
-
- // These values override the input value.
- private int keynum_ = -1;
- private int velocity_ = -1;
-
- private int initialAttenuation_ = 0; // in centibels.
-
- // All in log Hz.
- private double coarseTune_ = 0;
- private double fineTune_ = 0;
-
- enum SampleMode {
- NO_LOOP,
- LOOP_CONTINUOUSLY,
- LOOP_CONTINUOUSLY_THEN_FINISH,
- }
- private SampleMode sampleMode_ = SampleMode.NO_LOOP;
-
- private double scaleTuning_ = 0; // in log Hz per key.
- private int exclusiveClass_ = 0; // An id in range [1, 127], or 0 if not set.
- private int overridingRootKey_ = -1; // A key in range [0, 127], or -1 if not set.
-
- // All of the modulators in this zone. This is ignored.
- private ArrayList modulatorList_;
-}
diff --git a/core/src/com/levien/synthesizer/core/wave/RiffInputStream.java b/core/src/com/levien/synthesizer/core/wave/RiffInputStream.java
deleted file mode 100644
index 73c8b37..0000000
--- a/core/src/com/levien/synthesizer/core/wave/RiffInputStream.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.levien.synthesizer.core.wave;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * A wrapper around an InputStream that provides some utility functions for reading RIFF files.
- */
-public class RiffInputStream extends FilterInputStream {
- /**
- * Creates a new RiffInputStream wrapping the given input stream.
- */
- public RiffInputStream(InputStream in) {
- super(in);
- }
-
- /**
- * Skips the specified number of bytes in the input.
- */
- public void skipBytes(long bytes) throws IOException {
- while (bytes > 0) {
- int skipped = (int)skip(bytes);
- if (skipped <= 0) {
- throw new IOException("Error skipping bytes.");
- }
- bytes -= skipped;
- }
- }
-
- /**
- * Reads one signed byte from an input stream.
- * @param output - the stream to read from.
- * @return the signed byte read.
- * @throws IOException - on any kind of read error or EOF.
- */
- public byte readChar() throws IOException {
- return (byte)readByte();
- }
-
- /**
- * Reads one unsigned byte from an input stream.
- * @param output - the stream to read from.
- * @return the unsigned byte read.
- * @throws IOException - on any kind of read error or EOF.
- */
- public short readByte() throws IOException {
- int b = read();
- if (b < 0) {
- throw new IOException("Unexpected EOF while reading byte.");
- }
- return (short)(b & 0xFF);
- }
-
- /**
- * Checks that the given String matches the next bytes in the input stream.
- * @param input - the stream to read from.
- * @param data - the String to check for.
- * @throws IOException - On any kind of read error or if the exact string wasn't found.
- */
- public void checkBytes(String data) throws IOException {
- byte[] bytes = data.getBytes();
- for (int i = 0; i < bytes.length; ++i) {
- int b = read();
- if (b < 0) {
- throw new IOException("Expected " + bytes[i] + ", got EOF, while looking for " + data);
- }
- if ((byte)b != bytes[i]) {
- throw new IOException("Expected " + bytes[i] + ", got " + (byte)b +
- ", while looking for " + data);
- }
- }
- }
-
- /**
- * Reads the given number of bytes and returns an array of them.
- * @param input - the stream to read from.
- * @param size - the number of bytes to read.
- * @throws IOException - On any kind of read error or EOF.
- */
- public byte[] readBytes(int size) throws IOException {
- // TODO(klimt): This could be more efficient.
- byte[] bytes = new byte[size];
- int length = 0;
- for (length = 0; length < bytes.length; ++length) {
- int b = read();
- if (b < 0) {
- throw new IOException("Unexpected EOF while reading bytes.");
- }
- bytes[length] = (byte)b;
- }
- return bytes;
- }
-
- /**
- * Reads a string of the given size from the input stream.
- * I'm not sure what happens if it's not ASCII.
- * @param input - the stream to read from.
- * @param size - the number of bytes to read.
- * @throws IOException - On any kind of read error or if the exact string wasn't found.
- */
- public String readString(int size) throws IOException {
- byte[] bytes = new byte[size];
- int length = 0;
- for (length = 0; length < bytes.length; ++length) {
- int b = read();
- if (b < 0) {
- throw new IOException("Unexpected EOF while reading string.");
- }
- if (b == 0) {
- skipBytes(size - (length + 1));
- break;
- }
- bytes[length] = (byte)b;
- }
- String s = new String(bytes, 0, length);
- if (s.length() > size) {
- throw new IOException("Read string \"" + s + "\" longer than " + size + " bytes.");
- }
- return s;
- }
-
- /**
- * Reads one unsigned dword (32 bits) from an input stream in little-endian format.
- * @param input - the stream to read from.
- * @return - the unsigned dword read.
- * @throws IOException - on any kind of read error or EOF.
- */
- public long readDWord() throws IOException {
- long byte1 = read();
- long byte2 = read();
- long byte3 = read();
- long byte4 = read();
- if (byte1 < 0 || byte2 < 0 || byte3 < 0 || byte4 < 0) {
- throw new IOException("Unexpected EOF while reading int32.");
- }
- return (byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1;
- }
-
- /**
- * Reads one signed word (16 bits) from an input stream in little-endian format.
- * @param output - the stream to read from.
- * @return the signed word read.
- * @throws IOException - on any kind of read error or EOF.
- */
- public short readShort() throws IOException {
- return (short)readWord();
- }
-
- /**
- * Reads one unsigned word (16 bits) from an input stream in little-endian format.
- * @param output - the stream to read from.
- * @return the unsigned word read.
- * @throws IOException - on any kind of read error or EOF.
- */
- public int readWord() throws IOException {
- int lower = read();
- int upper = read();
- if (lower < 0 || upper < 0) {
- throw new IOException("Unexpected EOF while reading int16.");
- }
- int value = (int)(((upper << 8) | lower) & 0xFFFF);
- return value;
- }
-}
diff --git a/core/src/com/levien/synthesizer/core/wave/WaveAdapter.java b/core/src/com/levien/synthesizer/core/wave/WaveAdapter.java
deleted file mode 100644
index 71f1ce6..0000000
--- a/core/src/com/levien/synthesizer/core/wave/WaveAdapter.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.wave;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.levien.synthesizer.core.model.CachedSignalProvider;
-import com.levien.synthesizer.core.model.SignalProvider;
-import com.levien.synthesizer.core.model.SynthesisTime;
-
-/**
- * A WaveAdapter wraps a synthesizer component and allows siphoning off its output and writing it to
- * a wave file.
- * @see WaveWriter
- */
-public class WaveAdapter extends CachedSignalProvider {
- /**
- * Creates a new WaveAdapter.
- * @param sampleRate - The sample rate of the synthesizer in Hz.
- * @param bitsPerSample - The bits per sample of the wave file to write. Should be 8 or 16.
- * @param source - The synthesizer component to siphon output from.
- */
- public WaveAdapter(int sampleRate, int bitsPerSample, SignalProvider source) {
- logger_ = Logger.getLogger(getClass().getName());
- sampleRate_ = sampleRate;
- bitsPerSample_ = bitsPerSample;
- source_ = source;
- }
-
- /**
- * Starts the WaveAdapter recording for a specified length of time.
- * @param seconds - The length of time to record.
- * @parma output - The stream to write the output to.
- */
- public synchronized void startRecording(double seconds, OutputStream output) {
- if (writer_ != null) {
- try {
- writer_.close();
- } catch (IOException e) {
- logger_.log(Level.SEVERE, "Unable to close wave file.", e);
- }
- writer_ = null;
- }
- writer_ = new WaveWriter(sampleRate_, bitsPerSample_);
- logger_.info("Recording " + seconds + " seconds to file.");
- try {
- writer_.startRecording(seconds, output);
- } catch (IOException e) {
- logger_.log(Level.SEVERE, "Unable to open wave file for writing.", e);
- }
- }
-
- /**
- * Reads one sample from source, writes it to output, and returns it.
- */
- @Override
- protected synchronized double computeValue(SynthesisTime time) {
- double value = source_.getValue(time);
- if (writer_ != null) {
- try {
- if (!writer_.writeSample(value)) {
- // The file is full.
- logger_.info("Finished writing wave file.");
- close();
- }
- } catch (IOException e) {
- logger_.log(Level.SEVERE, "Unable to write sample to wave file. Aborting.", e);
- close();
- }
- }
- return value;
- }
-
- /**
- * Makes sure the file is closed. You don't need to call this between recordings, but only when
- * you are done, to make sure the last wave file was closed. If the file has already finished
- * recording, then this method will not do anything.
- */
- public synchronized void close() {
- if (writer_ != null) {
- try {
- writer_.close();
- } catch (IOException e) {
- logger_.log(Level.SEVERE, "Unable to close the wave file. Aborting.", e);
- }
- writer_ = null;
- }
- }
-
- // The sample rate of the source and output, in Hz.
- private int sampleRate_;
-
- // The number of bits per sample specified when creating the file. Should be 8 or 16.
- private int bitsPerSample_;
-
- // The synthesizer module to siphon output from.
- private SignalProvider source_;
-
- // The underlying writer that does the real work of creating the wave file.
- private WaveWriter writer_;
-
- private Logger logger_;
-}
diff --git a/core/src/com/levien/synthesizer/core/wave/WaveReader.java b/core/src/com/levien/synthesizer/core/wave/WaveReader.java
deleted file mode 100644
index f3b5113..0000000
--- a/core/src/com/levien/synthesizer/core/wave/WaveReader.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.wave;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.logging.Logger;
-
-/**
- * Reads a WAVE file from a stream and provides access its data.
- */
-public class WaveReader {
- /**
- * Reads the WAVE file from a stream and stores the data in a buffer.
- * @param input - the stream to read from.
- * @throws IOExpection - on a malformed or unsupported file format.
- */
- public WaveReader(InputStream in) throws IOException {
- Logger logger = Logger.getLogger(getClass().getName());
- logger.info("Loading WAVE file.");
-
- RiffInputStream input = new RiffInputStream(in);
-
- // Header.
- input.checkBytes("RIFF");
- logger.info("Read RIFF");
- @SuppressWarnings("unused")
- int chunkSize = (int)input.readDWord();
- input.checkBytes("WAVE");
-
- // Sub-chunk 1.
- input.checkBytes("fmt ");
- int subChunk1Size = (int)input.readDWord();
- if (subChunk1Size != 16) {
- throw new IOException("Format is not PCM.");
- }
- int audioFormat = input.readWord();
- if (audioFormat != 1) {
- throw new IOException("Unsupported compression scheme: " + audioFormat);
- }
- numChannels_ = input.readWord();
- if (numChannels_ != 1 && numChannels_ != 2) {
- throw new IOException("Unsupported number of channels: " + numChannels_);
- }
- sampleRateInHz_ = (int)input.readDWord();
- @SuppressWarnings("unused")
- int byteRate = (int)input.readDWord();
- @SuppressWarnings("unused")
- int blockAlign = input.readWord();
- int bitsPerSample = input.readWord();
- if (bitsPerSample != 8 && bitsPerSample != 16) {
- throw new IOException("Unsupported bits per sample: " + bitsPerSample);
- }
- int bytesPerSample = bitsPerSample / 8;
-
- // Sub-chunk 2.
- input.checkBytes("data");
- int subChunk2Size = (int)input.readDWord();
-
- // Actual data.
- int numSamples = subChunk2Size / (numChannels_ * bytesPerSample);
- leftChannel_ = new double[numSamples];
- rightChannel_ = new double[numSamples];
- for (int i = 0; i < numSamples; ++i) {
- switch (bitsPerSample) {
- case 8:
- leftChannel_[i] = input.readChar() / 128.0;
- break;
- case 16:
- leftChannel_[i] = input.readShort() / 32768.0;
- break;
- }
- if (numChannels_ == 2) {
- switch (bitsPerSample) {
- case 8:
- rightChannel_[i] = input.readChar() / 128.0;
- break;
- case 16:
- rightChannel_[i] = input.readShort() / 32768.0;
- break;
- }
- } else {
- rightChannel_[i] = leftChannel_[i];
- }
- }
-
- input.close();
- }
-
- /**
- * Returns the sample rate of the wave file.
- */
- public int getSampleRateInHz() {
- return sampleRateInHz_;
- }
-
- /**
- * Returns the number of samples in the wave file.
- */
- public int getSize() {
- return leftChannel_.length;
- }
-
- /**
- * Returns the nth sample from the left channel of the wave file.
- * If it's a mono file, returns the one sample.
- */
- public double getLeftSample(int i) {
- return leftChannel_[i];
- }
-
- /**
- * Returns the nth sample from the right channel of the wave file.
- * If it's a mono file, returns the one sample.
- */
- public double getRightSample(int i) {
- return rightChannel_[i];
- }
-
- /**
- * Returns the nth sample from the wave file.
- * If it's a mono file, returns the one sample. It it's stereo, returns the average.
- */
- public double getMonoSample(int i) {
- return (leftChannel_[i] + rightChannel_[i]) / 2;
- }
-
- // The number of channels in the file.
- private int numChannels_;
-
- // The sample rate of the file.
- private int sampleRateInHz_;
-
- // The samples in the file.
- private double[] leftChannel_;
- private double[] rightChannel_;
-}
diff --git a/core/src/com/levien/synthesizer/core/wave/WaveWriter.java b/core/src/com/levien/synthesizer/core/wave/WaveWriter.java
deleted file mode 100644
index b490889..0000000
--- a/core/src/com/levien/synthesizer/core/wave/WaveWriter.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.core.wave;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * WaveWriter is a class for writing sampled audio data to an output stream as a wave file.
- * To use it, call startRecording. Then call writeSample until it returns false. Then call close.
- * @see WaveAdapter
- */
-public class WaveWriter {
- /**
- * Creates a new WaveWriter with the given parameters.
- * @param sampleRate - The sample rate in Hz.
- * @param bitsPerSample - The size of each sample. Should be 8 or 16.
- * 8-bit is assumed to be unsigned. 16-bit is assumed to be signed.
- */
- public WaveWriter(int sampleRate, int bitsPerSample) {
- sampleRate_ = sampleRate;
- bitsPerSample_ = bitsPerSample;
- if (bitsPerSample_ != 8 && bitsPerSample_ != 16) {
- throw new RuntimeException(
- "Unacceptable bits per sample: " + bitsPerSample_ + ". Try 8 or 16.");
- }
- samples_ = 0;
- output_ = null;
- }
-
- /**
- * Initializes the wave file and writes its header.
- * @param seconds - How many seconds of recording to do.
- * @param output - The stream to write the wave file to.
- * @throws IOException - On any kind of write error.
- */
- public void startRecording(double seconds, OutputStream output) throws IOException {
- if (output_ != null) {
- close();
- }
-
- samples_ = (int)Math.round(sampleRate_ * seconds);
- try {
- output_ = output;
-
- writeBytes("RIFF", output_);
- writeLittle32(chunkSize(samples_), output_);
- writeBytes("WAVE", output_);
-
- // Sub-chunk 1
- writeBytes("fmt ", output_);
- writeLittle32(16, output_);
- writeLittle16(1, output_);
- writeLittle16(numChannels(), output_);
- writeLittle32(sampleRate_, output_);
- writeLittle32(byteRate(), output_);
- writeLittle16(blockAlign(), output_);
- writeLittle16(bitsPerSample(), output_);
-
- // Sub-chunk 2
- writeBytes("data", output_);
- writeLittle32(subChunk2Size(samples_), output_);
- } catch (IOException e) {
- if (output_ != null) {
- output_.close();
- }
- output_ = null;
- samples_ = 0;
- throw e;
- }
- }
-
- /**
- * Writes one sample of audio data to the file. Closes the stream when the file is full.
- * @param sample - The value to output, expected to be in the range [-1, 1].
- * @return False when the sample can't be written because the file is full. True otherwise.
- * @throws IOException - On any kind of write error.
- */
- public boolean writeSample(double sample) throws IOException {
- if (samples_ == 0) {
- return false;
- }
- // Clamp values out of range.
- if (sample < -1.0) {
- sample = -1.0;
- }
- if (sample > 1.0) {
- sample = 1.0;
- }
- try {
- if (bitsPerSample() == 16) {
- short shortSample = (short)(32767 * sample);
- writeLittle16(shortSample, output_);
- } else if (bitsPerSample() == 8) {
- writeByte((int)(255 * sample + 127.5), output_);
- }
- --samples_;
- if (samples_ == 0) {
- output_.close();
- }
- } catch (IOException e) {
- if (output_ != null) {
- output_.close();
- output_ = null;
- }
- samples_ = 0;
- throw e;
- }
- return true;
- }
-
- /**
- * Pads the file until it is the pre-specified length, and then closes the stream.
- */
- public void close() throws IOException {
- while (samples_ > 0) {
- writeSample(0.0);
- }
- output_.close();
- }
-
- /**
- * Returns the chunk size for the wave header.
- */
- private int chunkSize(int samples) {
- return 36 + subChunk2Size(samples);
- }
-
- /**
- * Returns the second sub-chunk size for the wave header.
- */
- private int subChunk2Size(int samples) {
- return samples * numChannels() * bitsPerSample() / 8;
- }
-
- /**
- * Returns the number of channels for the wave file.
- */
- private int numChannels() {
- return 1;
- }
-
- /**
- * Returns the bytes per second of the wave file.
- */
- private int byteRate() {
- return sampleRate_ * numChannels() * bitsPerSample() / 8;
- }
-
- /**
- * Returns the block-align parameter for the wave header.
- */
- private int blockAlign() {
- return numChannels() * bitsPerSample() / 8;
- }
-
- /**
- * Returns the bits per sample used when creating the WaveWriter.
- */
- private int bitsPerSample() {
- return bitsPerSample_;
- }
-
- /**
- * Writes one byte to an output stream.
- * @param data - The unsigned byte to write.
- * @param output - The stream to write to.
- * @throws IOException - On any kind of write error.
- */
- private static void writeByte(int data, OutputStream output) throws IOException {
- output.write(data);
- }
-
- /**
- * Writes a String to an output stream as bytes.
- * @param data - The bytes to write.
- * @param output - The stream to write to.
- * @throws IOException - On any kind of write error.
- */
- private static void writeBytes(String data, OutputStream output) throws IOException {
- output.write(data.getBytes());
- }
-
- /**
- * Writes one dword (32 bits) to an output stream in little-endian format.
- * @param data - The dword to write.
- * @param output - The stream to write to.
- * @throws IOException - On any kind of write error.
- */
- private static void writeLittle32(int data, OutputStream output) throws IOException {
- output.write(data & 0xFF);
- output.write((data >> 8) & 0xFF);
- output.write((data >> 16) & 0xFF);
- output.write((data >> 24) & 0xFF);
- }
-
- /**
- * Writes one word (16 bits) to an output stream in little-endian format.
- * @param data - The word to write.
- * @param output - The stream to write to.
- * @throws IOException - On any kind of write error.
- */
- private static void writeLittle16(int data, OutputStream output) throws IOException {
- output.write(data & 0xFF);
- output.write((data >> 8) & 0xFF);
- }
-
- // The number of samples left to write until the file is full.
- private int samples_;
- // The sample rate in Hz.
- private int sampleRate_;
- // The number of bits per output sample. Should be 8 or 16.
- private int bitsPerSample_;
- // The output stream to write the wave file to.
- private OutputStream output_;
-}
diff --git a/cpp/README b/cpp/README
deleted file mode 100644
index e715643..0000000
--- a/cpp/README
+++ /dev/null
@@ -1,24 +0,0 @@
-README for C++ codebase
-
-The C++ codebase will eventually be the primary sound generation module
-for this app. It's still experimental, and not yet wired up to the Android
-parts, but can be used to make sound. The best way is to use the simple
-test app for the Mac.
-
-To build, edit src/SynthApp/SynthMain.mm to change the path to ROM1A.SYX
-to the actual path. These patches can be downloaded from:
-
-http://www.abdn.ac.uk/~mth192/dx7/dx7patch.zip
-
-Also change the "KeyRig 49" string to match the actual USB name of your
-MIDI controller. Then "open src/SynthApp.xcodeproj", then do "Build and
-Run".
-
-The File Open menu command is hooked up as well and will load SYX format
-DX7 patch files (32 patches per file). Send program change midi events
-with the first 32 program numbers.
-
-The xcodeproj files are checked into the repo, but they are autogenerated
-from .gyp files, which are the authoritative masters. To modify the
-build, change the .gyp file, then run "gyp" in this dir. For changes
-to the core, also change ../../android/jni/Android.mk .
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..1d3591c
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,18 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..13372ae
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..122a0dc
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Mon Dec 28 10:00:20 PST 2015
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..9d82f78
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..aec9973
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/j2se/.classpath b/j2se/.classpath
deleted file mode 100644
index a3d94e2..0000000
--- a/j2se/.classpath
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/j2se/.externalToolBuilders/Proto Builder.launch b/j2se/.externalToolBuilders/Proto Builder.launch
deleted file mode 100644
index 68b4dfa..0000000
--- a/j2se/.externalToolBuilders/Proto Builder.launch
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/j2se/.gitignore b/j2se/.gitignore
deleted file mode 100644
index 6c3adb3..0000000
--- a/j2se/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-build/**
-j2se.jar
\ No newline at end of file
diff --git a/j2se/.project b/j2se/.project
deleted file mode 100644
index 8cc21b9..0000000
--- a/j2se/.project
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
- MusicSynthesizerJ2SE
-
-
-
-
-
- org.eclipse.ui.externaltools.ExternalToolBuilder
- auto,full,incremental,
-
-
- LaunchConfigHandle
- <project>/.externalToolBuilders/Proto Builder.launch
-
-
-
-
- org.eclipse.jdt.core.javabuilder
-
-
-
-
-
- org.eclipse.jdt.core.javanature
-
-
-
- core
- 2
- PARENT-1-PROJECT_LOC/core/src
-
-
- core-gen
- 2
- PARENT-1-PROJECT_LOC/core/gen
-
-
- core-lib
- 2
- PARENT-1-PROJECT_LOC/core/lib
-
-
- test
- 2
- PARENT-1-PROJECT_LOC/test/src
-
-
-
diff --git a/j2se/build.xml b/j2se/build.xml
deleted file mode 100644
index 6615363..0000000
--- a/j2se/build.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/j2se/src/com/levien/synthesizer/j2se/Midi.java b/j2se/src/com/levien/synthesizer/j2se/Midi.java
deleted file mode 100755
index ed43988..0000000
--- a/j2se/src/com/levien/synthesizer/j2se/Midi.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.j2se;
-
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Logger;
-import javax.sound.midi.MidiDevice;
-import javax.sound.midi.MidiMessage;
-import javax.sound.midi.MidiSystem;
-import javax.sound.midi.MidiUnavailableException;
-
-/**
- * Midi keeps track of the Midi devices connected to the system, and their control bindings.
- */
-public class Midi {
- /**
- * Creates a new Midi system for the given synthesizer.
- */
- public Midi(MultiChannelSynthesizer synth) {
- synthesizer_ = synth;
- binders_ = new ArrayList();
- logger_ = Logger.getLogger(getClass().getName());
- }
-
- /**
- * Prints out a list of all of the Midi devices connected to the system.
- */
- public void printDevices() {
- StringBuilder debug = new StringBuilder("\n");
- MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
- for (int i = 0; i < devices.length; ++i) {
- debug.append("Device " + i + ": " +
- devices[i].getName() + ": " + devices[i].getDescription() + "\n");
- debug.append(" " + devices[i].getVendor());
- debug.append(" " + devices[i].getVersion());
- try {
- MidiDevice device = MidiSystem.getMidiDevice(devices[i]);
- debug.append(" receivers: " + device.getMaxReceivers() +
- " transmitters: " + device.getMaxTransmitters() + "\n");
- } catch (MidiUnavailableException mue) {
- debug.append(" Unavailable!");
- }
- }
- logger_.info(debug.toString());
- }
-
- /**
- * Returns the Midi device at the specified index.
- */
- private MidiDevice getDevice(int index) {
- MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
- if (index < 0 || index >= devices.length) {
- return null;
- }
- try {
- return MidiSystem.getMidiDevice(devices[index]);
- } catch (MidiUnavailableException mue) {
- return null;
- }
- }
-
- /**
- * Connects the synthesizer to the controls of the Midi device at the specified index.
- */
- public void bindDevice(int index) {
- MidiDevice device = getDevice(index);
- if (device != null) {
- binders_.add(new MidiDeviceBinder(device, synthesizer_));
- } else {
- logger_.severe("Unable to get device with index " + index + ".");
- }
- }
-
- /**
- * Stops the connection to all Midi devices.
- */
- public void stop() {
- for (MidiDeviceBinder binder : binders_) {
- binder.stop();
- }
- }
-
- /**
- * Sends the given message to all Midi devices.
- */
- public void send(MidiMessage message) {
- for (MidiDeviceBinder binder : binders_) {
- binder.send(message);
- }
- }
-
- // The synthesizer to bind controls to.
- private MultiChannelSynthesizer synthesizer_;
-
- // The list of Midi device bindings.
- private List binders_;
-
- private Logger logger_;
-}
diff --git a/j2se/src/com/levien/synthesizer/j2se/MidiDeviceBinder.java b/j2se/src/com/levien/synthesizer/j2se/MidiDeviceBinder.java
deleted file mode 100644
index c69fc94..0000000
--- a/j2se/src/com/levien/synthesizer/j2se/MidiDeviceBinder.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.j2se;
-
-import com.levien.synthesizer.core.midi.MessageInputProcessor;
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.sound.midi.MidiDevice;
-import javax.sound.midi.MidiMessage;
-import javax.sound.midi.MidiUnavailableException;
-import javax.sound.midi.Receiver;
-import javax.sound.midi.Transmitter;
-
-/**
- * MidiDeviceBinder manages the connection between a MidiDevice and its associated BindingSet.
- */
-public class MidiDeviceBinder {
- /**
- * MidiDeviceBinder manages the connection between a MidiDevice and its associated BindingSet.
- * @param device - The device to connect the BindingSet to.
- * @param synth - The synthesizer to bind to.
- */
- public MidiDeviceBinder(MidiDevice device, MultiChannelSynthesizer synth) {
- device_ = device;
- synth_ = synth;
- midiIn_ = null;
- logger_ = Logger.getLogger(getClass().getName());
- try {
- if (midiIn_ == null && device_.getMaxTransmitters() != 0) {
- if (!device_.isOpen()) {
- device_.open();
- }
- midiIn_ = device_.getTransmitter();
- midiIn_.setReceiver(new Receiver() {
- public void send(MidiMessage message, long time) {
- ByteArrayInputStream stream = new ByteArrayInputStream(
- message.getMessage(), 0, message.getLength());
- try {
- MessageInputProcessor.process(stream, 0, synth_);
- } catch (IOException e) {
- logger_.log(Level.SEVERE, "Error processing Midi message.", e);
- }
- }
- public void close() {
- logger_.info("Closing MIDI receiver.");
- }
- });
- }
- if (midiOut_ == null && device_.getMaxReceivers() != 0) {
- if (!device_.isOpen()) {
- device_.open();
- }
- midiOut_ = device_.getReceiver();
- }
- } catch (MidiUnavailableException mue) {
- logger_.severe("Unable to open MIDI device.");
- midiIn_ = null;
- midiOut_ = null;
- }
- }
-
- /**
- * Closes the Midi device.
- */
- public void stop() {
- logger_.info("Closing MIDI device.");
- if (device_ != null) {
- device_.close();
- }
- if (midiIn_ != null) {
- midiIn_.close();
- midiIn_ = null;
- }
- if (midiOut_ != null) {
- midiOut_.close();
- midiOut_ = null;
- }
- }
-
- /**
- * Sends the given message to the Midi device.
- */
- public void send(MidiMessage message) {
- if (midiOut_ != null) {
- midiOut_.send(message, System.currentTimeMillis());
- }
- }
-
- // The synthesizer to bind to.
- private MultiChannelSynthesizer synth_;
-
- // The Midi device to bind to.
- private MidiDevice device_;
- private Transmitter midiIn_;
- private Receiver midiOut_;
-
- private Logger logger_;
-}
diff --git a/j2se/src/com/levien/synthesizer/j2se/Perform.java b/j2se/src/com/levien/synthesizer/j2se/Perform.java
deleted file mode 100644
index cf15417..0000000
--- a/j2se/src/com/levien/synthesizer/j2se/Perform.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.levien.synthesizer.j2se;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.sound.midi.MidiMessage;
-
-import com.levien.synthesizer.core.midi.MessageOutputProcessor;
-import com.levien.synthesizer.core.midi.MidiFilePlayer;
-import com.levien.synthesizer.core.midi.MidiListener;
-import com.levien.synthesizer.core.model.composite.MultiChannelSynthesizer;
-import com.levien.synthesizer.core.soundfont.SoundFontReader;
-import com.levien.synthesizer.core.wave.WaveAdapter;
-
-/**
- * Perform is a simple little command-line app for debugging the synthesizer.
- */
-public class Perform {
- /**
- * Loads presets from the given file into the synthesizer.
- * @param filename - The path to the file.
- * @param synth - The synthesizer to load the presets into.
- */
- public void loadPresetsFile(String filename, MultiChannelSynthesizer synth) {
- InputStream input;
- try {
- input = new BufferedInputStream(new FileInputStream(new File(filename)));
- try {
- synth.loadLibraryFromText(input);
- } catch (IOException e) {
- logger_.log(Level.SEVERE, "Unable to read from input stream.", e);
- }
- } catch (FileNotFoundException e) {
- logger_.severe("Unable to open file " + filename + ".");
- }
- }
-
- /**
- * This is dumb.
- */
- private static class DummyMidiMessage extends MidiMessage {
- protected DummyMidiMessage(byte[] data) {
- super(data);
- }
-
- @Override
- public Object clone() {
- return new DummyMidiMessage(getMessage());
- }
- }
-
- /**
- * The real main() function for this class. Creates a synthesizer and runs a read-eval-print loop
- * to take input from the user and control the synthesizer.
- */
- public Perform() {
- logger_ = Logger.getLogger(getClass().getName());
- double sampleRateInHz = 11025;
-
- SoundFontReader samples = null;
- try {
- samples = new SoundFontReader(new FileInputStream(new File("android/res/raw/drums.sf2")));
- } catch (IOException e) {
- samples = null;
- e.printStackTrace();
- }
-
- MultiChannelSynthesizer synth = new MultiChannelSynthesizer(16, 5, sampleRateInHz, samples);
- WaveAdapter writer = new WaveAdapter((int)sampleRateInHz, 16, synth);
-
- // Load some arbitrary presets to make playing midis more interesting.
- loadPresetsFile("android/res/raw/presets.txt", synth);
- synth.setPreset(0, 0);
- synth.setPreset(1, 1);
- synth.setPreset(2, 3);
- synth.setPreset(3, 0);
- synth.setPreset(4, 1);
- synth.setPreset(5, 1);
- synth.setPreset(6, 0);
- synth.setPreset(7, 0);
- synth.setPreset(8, 0);
- synth.setPreset(9, 5);
- synth.setPreset(10, 2);
- synth.setPreset(11, 0);
- synth.setPreset(12, 0);
- synth.setPreset(13, 0);
- synth.setPreset(14, 0);
- synth.setPreset(15, 0);
-
- final Midi midi = new Midi(synth);
- List listeners = new ArrayList();
- listeners.add(synth);
- listeners.add(new MessageOutputProcessor() {
- @Override
- protected void onMessage(byte[] message) {
- midi.send(new DummyMidiMessage(message));
- }
- });
- MidiFilePlayer player = new MidiFilePlayer(listeners);
-
- SynthesizerThread thread = new SynthesizerThread(writer, (int)sampleRateInHz);
- thread.play();
-
- boolean running = true;
- BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
- while (running) {
- String line = null;
- System.out.print("\n[synth]$ ");
- System.out.flush();
- try {
- line = stdin.readLine();
- } catch (IOException e) {
- logger_.log(Level.SEVERE, "Error reading line.", e);
- running = false;
- }
- if (line == null) {
- running = false;
- } else if (line.trim().equals("")) {
- // Do nothing.
- } else if (line.equals("exit") || line.equals("quit")) {
- running = false;
- } else if (line.equals("ls")) {
- midi.printDevices();
- } else if (line.equals("ls midi")) {
- midi.printDevices();
- } else if (line.equals("ls presets")) {
- ArrayList names = new ArrayList();
- synth.getPresetNames(names);
- StringBuilder output = new StringBuilder("");
- for (String name : names) {
- output.append("\n" + name);
- }
- logger_.info(output.toString());
- } else if (line.startsWith("bind ")) {
- String bindArgs = line.substring("bind ".length());
- try {
- int index = Integer.parseInt(bindArgs);
- midi.bindDevice(index);
- } catch (NumberFormatException e) {
- logger_.severe("Invalid number format \"" + bindArgs + "\".");
- }
- } else if (line.startsWith("presets ")) {
- String filename = line.substring("presets ".length());
- loadPresetsFile(filename, synth);
- } else if (line.startsWith("play ")) {
- String filename = line.substring("play ".length());
- try {
- player.play(new FileInputStream(filename));
- } catch (FileNotFoundException e) {
- logger_.log(Level.SEVERE, "Unable to open midi file.", e);
- } catch (IOException e) {
- logger_.log(Level.SEVERE, "Unable to read midi file.", e);
- }
- } else if (line.startsWith("record ")) {
- String[] args = line.split(" +", 3);
- if (args.length != 3) {
- logger_.severe("Usage: record