aboutsummaryrefslogtreecommitdiff
path: root/n2m.c
blob: cb67f934c18c9dd6c3a9cdd974212c5140b08693 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#ifdef _WIN32
#include "stdafx.h"
#include <io.h>
#endif
#include "m_pd.h"
#include <stdlib.h>
#include<time.h>
#include <string.h>
#include <stdio.h>
#include "n2m.h"

char* notes_up[12] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
int octaveoffset[11]  = {  0 , 12, 24 ,36, 48, 60, 72, 84, 96, 108 ,120 };

/**
*	The n2m object is designed to output a midi note number 
*	in response to a note name of the form <note name><octave>
*	for example C5 or D#3.
*/

static t_class *n2m_class;

/*
*	make a new n2m it takes one parameter - the percentage error
*/

static void *n2m_new( t_float f )
{
	t_n2m *x = (t_n2m *)pd_new(n2m_class);			    
	// make us an output for the note number
    outlet_new(&x->x_obj, gensym("float"));	
    return (x);
}

static void n2m_free(t_n2m *x)
{
	// nothing doing here for now
}

/**
*	set the error factor
*/

static void n2m_notename(  t_n2m *x, t_symbol *s, int ac, t_atom *av )
{
	char buf[255];	
	char note[255];
	int octave;
	int i;
	for(  i = 0 ; i < ac ; i++ )
	{
		atom_string( &av[i] , buf, 255 );
		//post("Symbol [%s]", buf );
		splitsym( buf , note , &octave );
		//post( "Which is %s note and %u octave and midi value %d" , note , octave , midilookup( note , octave ) );
		outlet_float( x->x_obj.ob_outlet , midilookup( note , octave ) );
	}	
}

/**
*	make a new one and setup all of our messages
*/

 void n2m_setup(void)
{
	 n2m_class = class_new(gensym("n2m"), (t_newmethod)n2m_new,
    	(t_method)n2m_free, sizeof(t_n2m), 0, 0);    
    class_addmethod(n2m_class, (t_method)n2m_notename, gensym("note" ), A_GIMME, 0);    	
	
}

/**
*	splitsym takes a note symbol and splits it into note and octave
*	if note not specified it defaults to C and if octave not specified 
*	it defaults to 4
*/

static void splitsym( char* buf , char* note, int* octave )
{
	int i,j;
	int split = -1;
	for( i = 0 ; buf[i] != 0 ; i++ )
	{
		if ( ( buf[i] >= '0' ) && ( buf[i] <= '9'))
		{
			split = i;
			if ( i > 0 )
			{
				for( j=0; j < i;j++) { note[j] = buf[j]; }
				note[i] = 0;
			}
			else
			{	
				note[0] = 'C';
				note[1] = 0;
			}
			sscanf( buf + i , "%u" , octave );
			break;
		}
	}
	if ( split == -1 )
	{
		i = 0;
		while( buf[i] != 0 )
		{
			note[i] = buf[i];
			i++;
		}
		note[i] = 0;
		*octave = 4;
	}
}

/**
*	return a midi note value for a given note name and octave 
*/

static int midilookup( char* note , int octave )
{
	int i,j;
	int nnum = 4;
	for( i = 0 ; i < 12 ; i++ )
	{
#ifdef NT
/* stricmp() is not an ANSI or ISO standard C function */
		if ( stricmp( note , notes_up[i]) == 0)
		{
			nnum = i;
			break;
		}
#else
/* replacing with a ANSI function, but it'll now be case sensitive */
		if ( strcmp( note , notes_up[i]) == 0)
		{
			nnum = i;
			break;
		}
#endif
	}
	return octaveoffset[octave + 1 ] + nnum;
}