1 /*---------------------------------------------------------------------------*
2 Project: Audio visualization tools
3 File: DEMOAVX.c
4
5 Copyright 2001 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Log: DEMOAVX.c,v $
14 Revision 2.0 2006/02/20 04:37:44 ceb
15 Ported from revolution to cafe.
16
17 Revision 1.2 2006/02/20 04:37:44 mitu
18 Changed include path from dolphin/ to revolution/.
19
20 Revision 1.1.1.1 2005/05/12 02:15:48 yasuh-to
21 Ported from dolphin sheath tree.
22
23
24 1 2002/01/11 4:55p Eugene
25 Cheesy method for snooping output from DSP/input to AI-FIFO. It is
26 audio-system agnostic, however.
27
28
29 $NoKeywords: $
30 *---------------------------------------------------------------------------*/
31
32 /*---------------------------------------------------------------------------*
33 * Includes
34 *---------------------------------------------------------------------------*/
35
36 #include <stdlib.h>
37 #include <stddef.h>
38 #include <string.h>
39 #include <math.h>
40
41 #include <cafe/demo.h>
42 #include <cafe/ai.h>
43
44 #define AVX_INTERNAL_NUM_FRAMES 10 // Buffer for up to 10 frames (in case the frame rate drops to around 20 fps).
45
46 ALIGNED_VAR(static s16, 32, __AVX_internal_buffer[AVX_FRAME_SIZE_WORDS*AVX_INTERNAL_NUM_FRAMES]);
47
48
49 static void (*__AVX_save_isr)(void); // AVX callback for the AI-FIFO DMA interrupt.
50
51 static u32 __AVX_num_frames; // Number of audio frames to buffer.
52 static u32 __AVX_num_filled; // Number of frames filled since the last user refresh.
53 static u32 __AVX_curr_frame;
54
55 static u16 *__AVX_buffer; // Internal AI-FIFO buffer.
56 static s16 *__AVX_left_buffer; // Pointer to the caller's left-channel sample buffer.
57 static s16 *__AVX_right_buffer; // Pointer to the caller's right-channel sample buffer.
58
59 static u32 __AVX_write_ptr = 0;
60 static u32 __AVX_buffer_size = 0;
61
62 static OSMutex __AVX_mutex;
63
64 /*---------------------------------------------------------------------------*
65 * Name :
66 * Description :
67 * Arguments : None.
68 * Returns : None.
69 *---------------------------------------------------------------------------*/
70
71 static BOOL flag = FALSE;
72
__DEMOAVX_isr(void)73 static void __DEMOAVX_isr(void)
74 {
75 u32 frame_address;
76
77 if (__AVX_save_isr)
78 {
79 (*__AVX_save_isr)();
80
81
82 // Get the current address of the current AI-FIFO DMA transaction.
83 frame_address = AIGetDMAStartAddr();
84
85 // Freak out if the address is NULL
86 ASSERTMSG(frame_address, "AVX: frame address is NULL!\n");
87
88 // Invalidate source (DSP output/AI-FIFO input)
89 //DCInvalidateRange((void *)(frame_address), AVX_FRAME_SIZE_BYTES);
90
91 // Copy output from DSP into the AVX buffer.
92 memcpy((void *)(&__AVX_buffer[__AVX_curr_frame * AVX_FRAME_SIZE_WORDS]), (void *)(frame_address), AVX_FRAME_SIZE_BYTES);
93
94 // Flush newly copied data from the cache.
95 //DCFlushRange((void *)(&__AVX_buffer[__AVX_curr_frame * AVX_FRAME_SIZE_WORDS]), AVX_FRAME_SIZE_BYTES);
96
97 // Increment the frame pointer.
98 __AVX_curr_frame = (__AVX_curr_frame + 1) % __AVX_num_frames;
99
100 // Increment the frame counter.
101 __AVX_num_filled = (__AVX_num_filled + 1) % AVX_INTERNAL_NUM_FRAMES;
102
103 if (__AVX_curr_frame > 4)
104 flag = TRUE;
105 }
106 } // end __DEMOAVX_isr
107
108 /*---------------------------------------------------------------------------*
109 * Name :
110 * Description :
111 * Arguments : None.
112 * Returns : None.
113 *---------------------------------------------------------------------------*/
114
115
DEMOAVXGetNumFilled(void)116 u32 DEMOAVXGetNumFilled(void)
117 {
118 u32 tmp;
119
120 OSLockMutex(&__AVX_mutex);
121
122 tmp = __AVX_num_filled;
123 __AVX_num_filled = 0;
124
125 OSUnlockMutex(&__AVX_mutex);
126
127 return(tmp);
128 } // end DEMOAVXGetNumFilled()
129
130 /*---------------------------------------------------------------------------*
131 * Name :
132 * Description :
133 * Arguments : None.
134 * Returns : None.
135 *---------------------------------------------------------------------------*/
136
DEMOAVXGetFrameCounter(void)137 u32 DEMOAVXGetFrameCounter(void)
138 {
139 return(__AVX_curr_frame);
140 } // end DEMOAVXGetFrameCounter()
141
142 /*---------------------------------------------------------------------------*
143 * Name :
144 * Description :
145 * Arguments : None.
146 * Returns : None.
147 *---------------------------------------------------------------------------*/
148
DEMOAVXRefreshBuffer(u32 * start_index,u32 * end_index)149 u32 DEMOAVXRefreshBuffer(u32 *start_index, u32 *end_index)
150 {
151 u32 num_filled;
152 u32 curr_frame;
153
154 u32 i;
155 u32 j;
156
157 if (flag)
158 {
159 OSLockMutex(&__AVX_mutex);
160 //
161 num_filled = DEMOAVXGetNumFilled();
162
163 // Rewind back through the AI buffer
164 curr_frame = (__AVX_num_frames + DEMOAVXGetFrameCounter() - num_filled) % __AVX_num_frames;
165
166 OSUnlockMutex(&__AVX_mutex);
167
168 // Save the starting position in the final sample buffer.
169 *start_index = __AVX_write_ptr;
170
171 for (i=0; i<num_filled; i++)
172 {
173 // Invalidate the AI buffer range
174 //DCInvalidateRange( (void *)(&__AVX_buffer[curr_frame * AVX_FRAME_SIZE_WORDS]), AVX_FRAME_SIZE_BYTES);
175
176 for (j=0; j<AVX_FRAME_SIZE_WORDS; j+=2)
177 {
178 __AVX_left_buffer [__AVX_write_ptr] = (s16)(__AVX_buffer[curr_frame * AVX_FRAME_SIZE_WORDS + j]);
179 __AVX_right_buffer[__AVX_write_ptr] = (s16)(__AVX_buffer[curr_frame * AVX_FRAME_SIZE_WORDS + j + 1]);
180
181 __AVX_write_ptr = (__AVX_write_ptr + 1) % __AVX_buffer_size;
182 }
183
184 curr_frame = (curr_frame + 1) % __AVX_num_frames;
185 }
186
187 *end_index = __AVX_write_ptr;
188
189 return(num_filled*AVX_FRAME_SIZE_SAMPLES);
190 }
191
192 return(0);
193 } // end DEMOAudioRefreshBuffer()
194
195 /*---------------------------------------------------------------------------*
196 * Name :
197 * Description :
198 * Arguments : None.
199 * Returns : None.
200 *---------------------------------------------------------------------------*/
201
DEMOAVXInit(s16 * left,s16 * right,u32 size)202 void DEMOAVXInit(s16 *left, s16 *right, u32 size)
203 {
204
205 __AVX_left_buffer = left;
206 __AVX_right_buffer = right;
207
208 __AVX_write_ptr = 0;
209
210 __AVX_buffer_size = size;
211
212 OSInitMutex(&__AVX_mutex);
213
214 DEMOAVXAttach((void *)__AVX_internal_buffer, AVX_INTERNAL_NUM_FRAMES);
215 } // end DEMOAVXInit()
216
217 /*---------------------------------------------------------------------------*
218 * Name :
219 * Description :
220 * Arguments : None.
221 * Returns : None.
222 *---------------------------------------------------------------------------*/
223
224
DEMOAVXAttach(void * buffer,u32 num_frames)225 void DEMOAVXAttach(void *buffer, u32 num_frames)
226 {
227 u32 i;
228
229 __AVX_buffer = (u16 *)buffer;
230 __AVX_num_frames = num_frames;
231 __AVX_num_filled = 0;
232 __AVX_curr_frame = 0;
233
234 // Clear the buffer.
235 for (i=0; i<(num_frames*AVX_FRAME_SIZE_WORDS); i++)
236 *(__AVX_buffer + i) = 0;
237
238 // Attach the AVX interrupt handler.
239 __AVX_save_isr = AIRegisterDMACallback(__DEMOAVX_isr);
240 } // end DEMOAVXAttach()
241