summaryrefslogtreecommitdiff
path: root/packages/libndsfpc/examples/audio/maxmod/streaming/streaming.pp
blob: f923e22d8b16fe81419d9e70cfd58ffbc4c02dd5 (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
program Streaming;

{$mode objfpc}

uses
  ctypes, nds9, maxmod9;
  

var
  sine: cint;  // sine position
  lfo: cint;   // LFO position

const
  // waveform base frequency
  sine_freq = 500;
  
  // LFO frequency
  lfo_freq = 3;
  
  // LFO output shift amount
  lfo_shift = 4;
  
  // blue backdrop
  bg_colour = 13 shl 10;
  
  // red cpu usage
  cpu_colour = 31;


function on_stream_request(aLength: mm_word; aDest: mm_addr; aFormat: mm_stream_formats): mm_word; 
var
  target: pcint16;
  len: cint;
  sample: cint;
begin	
	target := aDest;
	
	//------------------------------------------------------------
	// synthensize a sine wave with an LFO applied to the pitch
	// the stereo data is interleaved
	//------------------------------------------------------------
	len := aLength;
  while len <> 0 do
  begin
		sample := sinLerp(sine);
		
		// output sample for left
		target^ := sample;
		inc(target);
   
		// output inverted sample for right
		target^ := -sample;
		inc(target);
   
		sine := sine + sine_freq + (sinLerp(lfo) shr lfo_shift);
		lfo := (lfo + lfo_freq);
  
    dec(len);
  end;
	
	result := aLength;
end;

var
  sys: mm_ds_system;
  mystream: mm_stream;
begin	

	//----------------------------------------------------------------
	// print out some stuff
	//----------------------------------------------------------------
	consoleDemoInit();
	iprintf( #10'    Maxmod Streaming Example   '#10);

	//----------------------------------------------------------------
	// initialize maxmod without any soundbank (unusual setup)
	//----------------------------------------------------------------
	sys.mod_count 			:= 0;
	sys.samp_count			:= 0;
	sys.mem_bank			:= nil;
	sys.fifo_channel		:= FIFO_MAXMOD;
	mmInit( @sys );
	
	//----------------------------------------------------------------
	// open stream
	//----------------------------------------------------------------
	
	mystream.sampling_rate	:= 25000;					// sampling rate = 25khz
	mystream.buffer_length	:= 1200;						// buffer length = 1200 samples
	mystream.callback		:= @on_stream_request;		// set callback function
	mystream.format			:= MM_STREAM_16BIT_STEREO;	// format = stereo 16-bit
	mystream.timer			:= MM_TIMER0;				// use hardware timer 0
	mystream.manual			:= 1;						// use manual filling
	mmStreamOpen( @mystream );
		
	//----------------------------------------------------------------
	// when using 'automatic' filling, your callback will be triggered
	// every time half of the wave buffer is processed.
	//
	// so: 
	// 25000 (rate)
	// ----- = ~21 Hz for a full pass, and ~42hz for half pass
	// 1200  (length)
	//----------------------------------------------------------------
	// with 'manual' filling, you must call mmStreamUpdate
	// periodically (and often enough to avoid buffer underruns)
	//----------------------------------------------------------------
	
	SetYtrigger( 0 );
	irqEnable( IRQ_VCOUNT );
	
	while true do
	begin
		// wait until line 0
		swiIntrWait( 0, IRQ_VCOUNT);
		
		// update stream
		mmStreamUpdate();
		
		// restore backdrop (some lines were drawn with another colour to show cpu usage)
		BG_PALETTE_SUB[0] := bg_colour;
		
		// wait until next frame
		swiWaitForVBlank();
		
		// set backdrop to show cpu usage
		BG_PALETTE_SUB[0] := cpu_colour;
	end;
		
end.