OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [native/] [jni/] [midi-dssi/] [gnu_javax_sound_midi_dssi_DSSISynthesizer.c] - Blame information for rev 774

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 774 jeremybenn
/* gnu_javax_sound_midi_dssi_DSSISynthesizer.c - DSSI Synth
2
   Copyright (C) 2005 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
/* The original get_port_default() and set_control() routines were
39
 * copied from the DSSI source distribution and are covered by the
40
 * following copyright and license...
41
 *
42
 * Copyright 2004 Chris Cannam, Steve Harris and Sean Bolton.
43
 *
44
 * Permission to use, copy, modify, distribute, and sell this software
45
 * for any purpose is hereby granted without fee, provided that the
46
 * above copyright notice and this permission notice are included in
47
 * all copies or substantial portions of the software.
48
 */
49
 
50
#include <config.h>
51
#include <gnu_javax_sound_midi_dssi_DSSISynthesizer.h> 
52
#include <math.h>
53
 
54
#include "dssi_data.h"
55
 
56
/* Define this for debug output.  */
57
#undef DEBUG_DSSI_PROVIDER
58
 
59
static void set_control (dssi_data *data, snd_seq_event_t *event);
60
 
61
 
62
/**
63
 * The jack callback routine.
64
 *
65
 * This function is called by the jack audio system in its own thread
66
 * whenever it needs new audio data.
67
 *
68
 */
69
static int
70
process (jack_nframes_t nframes, void *arg)
71
{
72
  dssi_data *data = (dssi_data *) arg;
73
  int index;
74
  jack_default_audio_sample_t *buffer;
75
 
76
  /* Look through the event buffer to see if any control values
77
     need changing.  */
78
  for ( index = data->midiEventReadIndex;
79
        index != data->midiEventWriteIndex;
80
        index = (index + 1) % EVENT_BUFFER_SIZE)
81
    {
82
      if (data->midiEventBuffer[index].type == SND_SEQ_EVENT_CONTROLLER)
83
        set_control (data, & data->midiEventBuffer[index]);
84
    }
85
 
86
  if (data->desc->run_synth)
87
    {
88
      /* Call the synth audio processing routine.  */
89
      data->desc->run_synth
90
        (data->plugin_handle,
91
         nframes,
92
         &data->midiEventBuffer[data->midiEventReadIndex],
93
         data->midiEventWriteIndex - data->midiEventReadIndex);
94
    }
95
  else
96
    if (data->desc->run_multiple_synths)
97
      {
98
        snd_seq_event_t *events =
99
          &data->midiEventBuffer[data->midiEventReadIndex];
100
        unsigned long event_count =
101
          data->midiEventWriteIndex - data->midiEventReadIndex;
102
 
103
        /* Call the synth audio processing routine.  */
104
        data->desc->run_multiple_synths
105
          (1,
106
           & (data->plugin_handle),
107
           nframes,
108
           &events,
109
           &event_count);
110
      }
111
 
112
  /* Update the read index on our circular buffer.  */
113
  data->midiEventReadIndex = data->midiEventWriteIndex;
114
 
115
  /* Copy output from the synth to jack.
116
 
117
     FIXME: This is hack that only gets one channel from the synth and
118
     send that to both jack ports (until we handle stero synths
119
     properly).
120
 
121
     FIXME: Can we avoid this copying?  */
122
  buffer = jack_port_get_buffer(data->jack_left_output_port, nframes);
123
  memcpy (buffer, data->left_buffer, nframes * sizeof(LADSPA_Data));
124
  buffer = jack_port_get_buffer(data->jack_right_output_port, nframes);
125
  memcpy (buffer, data->left_buffer, nframes * sizeof(LADSPA_Data));
126
 
127
  return 0;
128
}
129
 
130
 
131
/**
132
 * Calculate a reasonable default value for a specific control port.
133
 * This is mostly copied from the DSSI example code.  Copyright info
134
 * is found at the top of this file.
135
 *
136
 */
137
static LADSPA_Data
138
get_port_default (const LADSPA_Descriptor *plugin,
139
                  int port, jack_nframes_t sample_rate)
140
{
141
  LADSPA_PortRangeHint hint = plugin->PortRangeHints[port];
142
  float lower = hint.LowerBound *
143
    (LADSPA_IS_HINT_SAMPLE_RATE(hint.HintDescriptor) ? sample_rate : 1.0f);
144
  float upper = hint.UpperBound *
145
    (LADSPA_IS_HINT_SAMPLE_RATE(hint.HintDescriptor) ? sample_rate : 1.0f);
146
 
147
  if (!LADSPA_IS_HINT_HAS_DEFAULT(hint.HintDescriptor))
148
    {
149
      if (!LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor) ||
150
          !LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor))
151
        {
152
          /* No hint, its not bounded, wild guess */
153
          return 0.0f;
154
        }
155
 
156
      if (lower <= 0.0f && upper >= 0.0f)
157
        {
158
          /* It spans 0.0, 0.0 is often a good guess */
159
          return 0.0f;
160
        }
161
 
162
      /* No clues, return minimum */
163
      return lower;
164
    }
165
 
166
  /* Try all the easy ones */
167
 
168
  if (LADSPA_IS_HINT_DEFAULT_0(hint.HintDescriptor))
169
    return 0.0f;
170
  else if (LADSPA_IS_HINT_DEFAULT_1(hint.HintDescriptor))
171
    return 1.0f;
172
  else if (LADSPA_IS_HINT_DEFAULT_100(hint.HintDescriptor))
173
    return 100.0f;
174
  else if (LADSPA_IS_HINT_DEFAULT_440(hint.HintDescriptor))
175
    return 440.0f;
176
 
177
  /* All the others require some bounds */
178
 
179
  if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor)
180
      && (LADSPA_IS_HINT_DEFAULT_MINIMUM(hint.HintDescriptor)))
181
    return lower;
182
 
183
  if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor))
184
    {
185
      if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(hint.HintDescriptor))
186
        return upper;
187
 
188
      if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor))
189
        {
190
          if (LADSPA_IS_HINT_DEFAULT_LOW(hint.HintDescriptor))
191
            return lower * 0.75f + upper * 0.25f;
192
          else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(hint.HintDescriptor))
193
            return lower * 0.5f + upper * 0.5f;
194
          else if (LADSPA_IS_HINT_DEFAULT_HIGH(hint.HintDescriptor))
195
            return lower * 0.25f + upper * 0.75f;
196
        }
197
    }
198
 
199
  /* fallback */
200
  return 0.0f;
201
}
202
 
203
/**
204
 * Set a control value by mapping the MIDI event to a suitable value
205
 * for this control.
206
 * This is mostly copied from the DSSI example code.  Copyright info
207
 * is found at the top of this file.
208
 *
209
 */
210
static void
211
set_control(dssi_data *data, snd_seq_event_t *event)
212
{
213
  unsigned control = event->data.control.param;
214
  unsigned port = data->control_port_map[control];
215
 
216
  const LADSPA_Descriptor *p = data->desc->LADSPA_Plugin;
217
 
218
  LADSPA_PortRangeHintDescriptor d = p->PortRangeHints[port].HintDescriptor;
219
 
220
  LADSPA_Data lb = p->PortRangeHints[port].LowerBound *
221
    (LADSPA_IS_HINT_SAMPLE_RATE(p->PortRangeHints[port].HintDescriptor) ?
222
     data->sample_rate : 1.0f);
223
 
224
  LADSPA_Data ub = p->PortRangeHints[port].UpperBound *
225
    (LADSPA_IS_HINT_SAMPLE_RATE(p->PortRangeHints[port].HintDescriptor) ?
226
     data->sample_rate : 1.0f);
227
 
228
  float value = (float)event->data.control.value;
229
 
230
  if (!LADSPA_IS_HINT_BOUNDED_BELOW(d))
231
    {
232
      if (!LADSPA_IS_HINT_BOUNDED_ABOVE(d))
233
        {
234
          /* unbounded: might as well leave the value alone. */
235
        }
236
      else
237
        {
238
          /* bounded above only. just shift the range. */
239
          value = ub - 127.0f + value;
240
        }
241
    }
242
  else
243
    {
244
      if (!LADSPA_IS_HINT_BOUNDED_ABOVE(d))
245
        {
246
          /* bounded below only. just shift the range. */
247
          value = lb + value;
248
        }
249
      else
250
        {
251
          /* bounded both ends.  more interesting. */
252
          if (LADSPA_IS_HINT_LOGARITHMIC(d))
253
            {
254
              const float llb = logf(lb);
255
              const float lub = logf(ub);
256
 
257
              value = expf(llb + ((lub - llb) * value / 127.0f));
258
            }
259
          else
260
            {
261
              value = lb + ((ub - lb) * value / 127.0f);
262
            }
263
        }
264
    }
265
 
266
#ifdef DEBUG_DSSI_PROVIDER
267
  printf("MIDI controller %d=%d -> control in %u=%f\n",
268
         event->data.control.param,
269
         event->data.control.value,
270
         data->control_value_map[control], value);
271
#endif
272
 
273
  data->control_values[data->control_value_map[control]] = value;
274
}
275
 
276
/**
277
 * Open a new synthesizer.  This currently involves instantiating a
278
 * new synth, creating a new jack client connection, and activating
279
 * both.
280
 *
281
 */
282
JNIEXPORT void JNICALL
283
Java_gnu_javax_sound_midi_dssi_DSSISynthesizer_open_1
284
  (JNIEnv *env, jclass clazz __attribute__((unused)), jlong handle)
285
{
286
  unsigned int port_count, j, cindex;
287
  const char **ports;
288
  int controller = 0;
289
  dssi_data *data = (dssi_data *) (long) handle;
290
  if ((data->jack_client = jack_client_new (data->desc->LADSPA_Plugin->Label)) == 0)
291
    {
292
      /*        JCL_ThrowException (env, "javax/sound/midi/MidiUnavailableException",   */
293
      JCL_ThrowException (env, "java/io/IOException",
294
                          "can't create jack client");
295
      return;
296
    }
297
 
298
  /* Get the jack sample rate, which may be used in default control port
299
     value calculations.  */
300
  data->sample_rate = jack_get_sample_rate (data->jack_client);
301
 
302
  data->plugin_handle =
303
    (data->desc->LADSPA_Plugin->instantiate)(data->desc->LADSPA_Plugin,
304
                                             data->sample_rate);
305
 
306
  if (jack_set_process_callback (data->jack_client, process, data) != 0)
307
    {
308
      JCL_ThrowException (env, "java/io/IOException",
309
                          "can't set jack process callback");
310
      return;
311
    }
312
 
313
  data->jack_left_output_port =
314
    jack_port_register (data->jack_client, "output_left",
315
                        JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
316
  data->jack_right_output_port =
317
    jack_port_register (data->jack_client, "output_right",
318
                        JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
319
 
320
  /* Count the number of controls and audio ouput ports.  */
321
  port_count = data->control_count = 0;
322
  for (j = 0; j < data->desc->LADSPA_Plugin->PortCount; j++)
323
    {
324
      LADSPA_PortDescriptor pod =
325
        data->desc->LADSPA_Plugin->PortDescriptors[j];
326
 
327
      if (LADSPA_IS_PORT_AUDIO(pod) && LADSPA_IS_PORT_OUTPUT(pod))
328
        port_count++;
329
      else if (LADSPA_IS_PORT_CONTROL(pod) && LADSPA_IS_PORT_INPUT(pod))
330
        data->control_count++;
331
    }
332
 
333
  /* Allocate the array of control values.  */
334
  data->control_values =
335
    (LADSPA_Data *) JCL_malloc (env,
336
                                data->control_count * sizeof (LADSPA_Data));
337
 
338
  /* Initialize the MIDI control map.  */
339
  memset (data->control_value_map, 0, data->control_count * sizeof(unsigned));
340
 
341
  /* Create buffers for each port.  */
342
  for (cindex = 0, j = 0; j < data->desc->LADSPA_Plugin->PortCount; j++)
343
    {
344
      LADSPA_PortDescriptor pod =
345
        data->desc->LADSPA_Plugin->PortDescriptors[j];
346
      if (LADSPA_IS_PORT_AUDIO(pod) && LADSPA_IS_PORT_OUTPUT(pod))
347
        {
348
          data->left_buffer =
349
            (float *) calloc(jack_get_buffer_size(data->jack_client),
350
                             sizeof(float));
351
          (data->desc->LADSPA_Plugin->connect_port)(data->plugin_handle, j,
352
                                                    data->left_buffer);
353
        }
354
      else
355
        if (LADSPA_IS_PORT_CONTROL(pod) && LADSPA_IS_PORT_INPUT(pod))
356
          {
357
            /* This is an input control port.  Connect it to a properly
358
               initialized value in our controller value array.  */
359
            (data->desc->LADSPA_Plugin->connect_port)
360
              (data->plugin_handle, j, &(data->control_values[cindex]));
361
            data->control_values[cindex] =
362
              get_port_default (data->desc->LADSPA_Plugin,
363
                                j, data->sample_rate);
364
 
365
            /* Set up the mapping between MIDI controllers and this
366
               contoller value.  */
367
            if (data->desc->get_midi_controller_for_port)
368
              {
369
                controller = data->desc->
370
                  get_midi_controller_for_port(data->plugin_handle, j);
371
 
372
                if ((controller != DSSI_NONE) && DSSI_IS_CC(controller))
373
                  {
374
                    data->control_value_map[DSSI_CC_NUMBER(controller)] = cindex;
375
                    data->control_port_map[DSSI_CC_NUMBER(controller)] = j;
376
 
377
#ifdef DEBUG_DSSI_PROVIDER
378
                    printf ("MIDI Controller 0x%x [%s] = %g\n",
379
                            DSSI_CC_NUMBER(controller),
380
                            data->desc->LADSPA_Plugin->PortNames[j],
381
                            data->control_values[cindex]);
382
#endif
383
                  }
384
              }
385
 
386
            cindex++;
387
          }
388
    }
389
 
390
  (data->desc->LADSPA_Plugin->activate)(data->plugin_handle);
391
 
392
  if (jack_activate (data->jack_client))
393
    JCL_ThrowException (env, "java/io/IOException",
394
                        "can't activate jack client");
395
 
396
  /* Try to connect the synth output to hardware audio ports.  */
397
  ports = jack_get_ports (data->jack_client, NULL, NULL,
398
                          JackPortIsPhysical | JackPortIsInput);
399
  if (ports)
400
    {
401
      if (ports[0] && ports[1])
402
        {
403
          /* Don't bother checking return values.  Failing is OK.  */
404
          jack_connect (data->jack_client,
405
                        jack_port_name (data->jack_left_output_port),
406
                        ports[0]);
407
          jack_connect (data->jack_client,
408
                        jack_port_name (data->jack_right_output_port),
409
                        ports[1]);
410
        }
411
      free(ports);
412
    }
413
}
414
 
415
/**
416
 * This is called when we receive a new MIDI CONTROL CHANGE message.
417
 * Simply stick an appropriate event in the event buffer.  This will
418
 * get processed in the jack callback function.
419
 */
420
JNIEXPORT void JNICALL
421
Java_gnu_javax_sound_midi_dssi_DSSISynthesizer_controlChange_1
422
  (JNIEnv *env __attribute__((unused)), jclass clazz __attribute__((unused)),
423
   jlong handle, jint channel, jint control, jint value)
424
{
425
  dssi_data *data = JLONG_TO_PTR(dssi_data,handle);
426
 
427
  /* Insert this event in the event buffer.  */
428
  snd_seq_event_t *ev = & data->midiEventBuffer[data->midiEventWriteIndex];
429
 
430
  /* Set the event value.  */
431
  snd_seq_ev_set_controller (ev, channel, control, value);
432
 
433
  data->midiEventWriteIndex =
434
    (data->midiEventWriteIndex + 1) % EVENT_BUFFER_SIZE;
435
}
436
 
437
/**
438
 * This is called when we receive a new MIDI NOTE ON message.  Simply
439
 * stick an appropriate event in the event buffer.  This will get
440
 * processed in the jack callback function.
441
 */
442
JNIEXPORT void JNICALL
443
Java_gnu_javax_sound_midi_dssi_DSSISynthesizer_noteOn_1
444
  (JNIEnv *env __attribute__((unused)), jclass clazz __attribute__((unused)),
445
   jlong handle, jint channel, jint note, jint velocity)
446
{
447
  dssi_data *data = JLONG_TO_PTR(dssi_data,handle);
448
 
449
  /* Insert this event in the event buffer.  */
450
  snd_seq_event_t *ev = & data->midiEventBuffer[data->midiEventWriteIndex];
451
 
452
  ev->type = SND_SEQ_EVENT_NOTEON;
453
  ev->data.control.channel = channel;
454
  ev->data.note.note = note;
455
  ev->data.note.velocity = velocity;
456
 
457
  data->midiEventWriteIndex =
458
    (data->midiEventWriteIndex + 1) % EVENT_BUFFER_SIZE;
459
}
460
 
461
/**
462
 * This is called when we receive a new MIDI NOTE OFF message.  Simply
463
 * stick an appropriate event in the event buffer.  This will get
464
 * processed in the jack callback function.
465
 */
466
JNIEXPORT void JNICALL
467
Java_gnu_javax_sound_midi_dssi_DSSISynthesizer_noteOff_1
468
  (JNIEnv *env __attribute__((unused)),
469
   jclass clazz __attribute__((unused)),
470
   jlong handle, jint channel, jint note, jint velocity)
471
{
472
  dssi_data *data = JLONG_TO_PTR(dssi_data,handle);
473
 
474
  /* Insert this event in the event buffer.  */
475
  snd_seq_event_t *ev = & data->midiEventBuffer[data->midiEventWriteIndex];
476
 
477
  ev->type = SND_SEQ_EVENT_NOTEOFF;
478
  ev->data.control.channel = channel;
479
  ev->data.note.note = note;
480
  ev->data.note.velocity = velocity;
481
 
482
  data->midiEventWriteIndex =
483
    (data->midiEventWriteIndex + 1) % EVENT_BUFFER_SIZE;
484
}
485
 
486
JNIEXPORT void JNICALL
487
Java_gnu_javax_sound_midi_dssi_DSSISynthesizer_setPolyPressure_1
488
  (JNIEnv *env __attribute__((unused)), jclass clazz __attribute__((unused)),
489
   jlong handle __attribute__((unused)), jint channel __attribute__((unused)),
490
   jint note __attribute__((unused)), jint velocity __attribute__((unused)))
491
{
492
}
493
 
494
JNIEXPORT jint JNICALL
495
Java_gnu_javax_sound_midi_dssi_DSSISynthesizer_getPolyPressure_1
496
  (JNIEnv *env __attribute__((unused)), jclass clazz __attribute__((unused)),
497
   jlong handle __attribute__((unused)), jint channel __attribute__((unused)),
498
   jint note __attribute__((unused)))
499
{
500
  return 0;
501
}
502
 
503
JNIEXPORT void JNICALL
504
Java_gnu_javax_sound_midi_dssi_DSSISynthesizer_close_1
505
  (JNIEnv *env __attribute__((unused)), jclass clazz __attribute__((unused)),
506
   jlong handle __attribute__((unused)))
507
{
508
}
509
 
510
/* FIXME: These next three functions are really inefficient because
511
   we're instantiating and cleaning up plugin instances just to query
512
   values.  */
513
 
514
JNIEXPORT jstring JNICALL
515
Java_gnu_javax_sound_midi_dssi_DSSISynthesizer_getProgramName_1
516
  (JNIEnv *env, jclass clazz __attribute__((unused)),
517
   jlong handle, jint index)
518
{
519
  LADSPA_Handle lhandle;
520
  jstring name = (jstring) NULL;
521
  dssi_data *data = JLONG_TO_PTR(dssi_data, handle);
522
  if (data->desc->get_program == NULL)
523
    return NULL;
524
  lhandle =
525
    (data->desc->LADSPA_Plugin->instantiate)(data->desc->LADSPA_Plugin,
526
                                             48000);
527
  const DSSI_Program_Descriptor *program =
528
    (data->desc->get_program)(lhandle, (unsigned long) index);
529
  if (program)
530
    name = (*env)->NewStringUTF (env, program->Name);
531
  (data->desc->LADSPA_Plugin->cleanup)(lhandle);
532
 
533
  return name;
534
}
535
 
536
JNIEXPORT jint JNICALL
537
Java_gnu_javax_sound_midi_dssi_DSSISynthesizer_getProgramBank_1
538
  (JNIEnv *env __attribute__((unused)), jclass clazz __attribute__((unused)),
539
   jlong handle, jint index)
540
{
541
  LADSPA_Handle lhandle;
542
  jint result = -1;
543
  dssi_data *data = JLONG_TO_PTR(dssi_data, handle);
544
  lhandle =
545
    (data->desc->LADSPA_Plugin->instantiate)(data->desc->LADSPA_Plugin,
546
                                             48000);
547
  const DSSI_Program_Descriptor *program =
548
    (data->desc->get_program)(lhandle, (unsigned long) index);
549
  if (program)
550
    result = (jint) program->Bank;
551
  (data->desc->LADSPA_Plugin->cleanup)(lhandle);
552
  return result;
553
}
554
 
555
JNIEXPORT jint JNICALL
556
Java_gnu_javax_sound_midi_dssi_DSSISynthesizer_getProgramProgram_1
557
  (JNIEnv *env __attribute__((unused)), jclass clazz __attribute__((unused)),
558
   jlong handle, jint index)
559
{
560
  LADSPA_Handle lhandle;
561
  jint result = -1;
562
  dssi_data *data = JLONG_TO_PTR(dssi_data, handle);
563
  lhandle =
564
    (data->desc->LADSPA_Plugin->instantiate)(data->desc->LADSPA_Plugin,
565
                                             48000);
566
  const DSSI_Program_Descriptor *program =
567
    (data->desc->get_program)(lhandle, (unsigned long) index);
568
  if (program)
569
    result = (jint) program->Program;
570
  (data->desc->LADSPA_Plugin->cleanup)(lhandle);
571
  return result;
572
}
573
 
574
 
575
JNIEXPORT void JNICALL
576
Java_gnu_javax_sound_midi_dssi_DSSISynthesizer_selectProgram_1
577
  (JNIEnv *env __attribute__((unused)), jclass clazz __attribute__((unused)),
578
   jlong handle, jint bank, jint program)
579
{
580
  dssi_data *data = JLONG_TO_PTR(dssi_data, handle);
581
 
582
  (data->desc->select_program)(data->plugin_handle,
583
                               (unsigned) bank, (unsigned) program);
584
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.