Example #1
0
CItem* EventCanvas::getRightMostSelected()
{
    iCItem i, iRightmost;
    CItem* rightmost = NULL;

    // get a list of items that belong to the current part
    // since multiple parts have populated the _items list
    // we need to filter on the actual current Part!
    CItemList list = _items;
    if(multiPartSelectionAction && !multiPartSelectionAction->isChecked())
        list = getItemlistForCurrentPart();
    //CItemList list = getItemlistForCurrentPart();

    //Get the rightmost selected note (if any)
    i = list.begin();
    while (i != list.end())
    {
        if (i->second->isSelected())
        {
            iRightmost = i;
            rightmost = i->second;
        }

        ++i;
    }

    return rightmost;
}
Example #2
0
CItem* EventCanvas::getLeftMostSelected()
{
    iCItem i, iLeftmost;
    CItem* leftmost = NULL;

    // get a list of items that belong to the current part
    // since multiple parts have populated the _items list
    // we need to filter on the actual current Part!
    //CItemList list = getItemlistForCurrentPart();
    CItemList list = _items;
    if(multiPartSelectionAction && !multiPartSelectionAction->isChecked())
        list = getItemlistForCurrentPart();

    if (list.size() > 0)
    {
        i = list.end();
        while (i != list.begin())
        {
            --i;

            if (i->second->isSelected())
            {
                iLeftmost = i;
                leftmost = i->second;
            }
        }
    }

    return leftmost;
}
Example #3
0
QList<Event> AbstractMidiEditor::getSelectedEvents()/*{{{*/
{
    QList<Event> rv;
    if(canvas)
    {
        CItemList list = canvas->getSelectedItemsForCurrentPart();

        for (iCItem k = list.begin(); k != list.end(); ++k)
        {
            NEvent* nevent = (NEvent*) (k->second);
            Event event = nevent->event();
            if (event.type() != Note)
                continue;

            rv.append(event);
        }
    }
    return rv;
}/*}}}*/
Example #4
0
void EventCanvas::selectAtTick(unsigned int tick)/*{{{*/
{
    CItemList list = _items;
    if(multiPartSelectionAction && !multiPartSelectionAction->isChecked())
        list = getItemlistForCurrentPart();
    //CItemList list = getItemlistForCurrentPart();

    //Select note nearest tick, if none selected and there are any
    if (!list.empty() && selectionSize() == 0)
    {
        iCItem i = list.begin();
        CItem* nearest = i->second;

        while (i != list.end())
        {
            CItem* cur = i->second;
            unsigned int curtk = abs(cur->x() + cur->part()->tick() - tick);
            unsigned int neartk = abs(nearest->x() + nearest->part()->tick() - tick);

            if (curtk < neartk)
            {
                nearest = cur;
            }

            i++;
        }

        if (!nearest->isSelected())
        {
            selectItem(nearest, true);
            if(editor->isGlobalEdit())
                populateMultiSelect(nearest);
            songChanged(SC_SELECTION);
        }
        itemPressed(nearest);
        m_tempPlayItems.append(nearest);
        QTimer::singleShot(NOTE_PLAY_TIME, this, SLOT(playReleaseForItem()));
    }
}/*}}}*/
Example #5
0
void EventCanvas::populateMultiSelect(CItem* baseItem)/*{{{*/
{
    if(editor->isGlobalEdit() && baseItem)
    {
        PartList* pl = editor->parts();
        int curTranspose = ((MidiTrack*)baseItem->part()->track())->getTransposition();
        Event curEvent = baseItem->event();
        int curPitch = curEvent.pitch();
        int curRawPitch = curPitch - curTranspose;
        //int curLen = curEvent.lenTick();
        m_multiSelect.clear();
        for(iPart p = pl->begin(); p != pl->end(); ++p)
        {
            if(p->second == _curPart)
                continue;
            CItemList pitems = getItemlistForPart(p->second);
            for (iCItem i = pitems.begin(); i != pitems.end(); ++i)
            {
                MidiTrack* mtrack = (MidiTrack*)i->second->part()->track();
                int transp = mtrack->getTransposition();
                Event e = i->second->event();
                if(e.empty())
                    continue;
                int pitch = e.pitch();
                int rpitch = pitch - transp;
                //int len = e.lenTick();
                //printf("Current pitch: %d, rawpitch: %d - note pitch: %d, raw: %d\n", curPitch, curRawPitch, pitch, rpitch);
                if(e.tick() == curEvent.tick() && rpitch == curRawPitch/*, len == curLen*/)
                {
                    m_multiSelect.add(i->second);
                        break;
                }
            }
        }
        //printf("MultiSelect list size: %d \n", (int)m_multiSelect.size());
    }
}/*}}}*/
Example #6
0
void EventCanvas::actionCommand(int action)/*{{{*/
{
    switch(action)
    {
        case LOCATORS_TO_SELECTION:
        {
            int tick_max = 0;
            int tick_min = INT_MAX;
            bool found = false;

            for (iCItem i = _items.begin(); i != _items.end(); i++)
            {
                if (!i->second->isSelected())
                    continue;

                int tick = i->second->x();
                int len = i->second->event().lenTick();
                found = true;
                if (tick + len > tick_max)
                    tick_max = tick + len;
                if (tick < tick_min)
                    tick_min = tick;
            }
            if (found)
            {
                Pos p1(tick_min, true);
                Pos p2(tick_max, true);
                song->setPos(1, p1);
                song->setPos(2, p2);
            }
        }
        break;
        case  SEL_RIGHT ... SEL_RIGHT_ADD:
        {
            if (action == SEL_RIGHT && allItemsAreSelected())
            {
                deselectAll();
                selectAtTick(song->cpos());
                return;
            }

            iCItem i, iRightmost;
            CItem* rightmost = NULL;

            // get a list of items that belong to the current part
            // since multiple parts have populated the _items list
            // we need to filter on the actual current Part!
            CItemList list = _items;
            if(multiPartSelectionAction && !multiPartSelectionAction->isChecked())
                list = getItemlistForCurrentPart();

            //Get the rightmost selected note (if any)
            i = list.begin();
            while (i != list.end())
            {
                if (i->second->isSelected())
                {
                    iRightmost = i;
                    rightmost = i->second;
                }

                ++i;
            }
            if (rightmost)
            {
                iCItem temp = iRightmost;
                temp++;
                //If so, deselect current note and select the one to the right
                if (temp != list.end())
                {
                    if (action != SEL_RIGHT_ADD)
                        deselectAll();

                    iRightmost++;
                    iRightmost->second->setSelected(true);
                    itemPressed(iRightmost->second);
                    m_tempPlayItems.append(iRightmost->second);
                    QTimer::singleShot(NOTE_PLAY_TIME, this, SLOT(playReleaseForItem()));
                    if(editor->isGlobalEdit())
                        populateMultiSelect(iRightmost->second);
                    updateSelection();
                }
            }
            else // there was no item selected at all? Then select nearest to tick if there is any
            {
                selectAtTick(song->cpos());
                updateSelection();
            }
        }
        break;
        case SEL_LEFT ... SEL_LEFT_ADD:
        {
            if (action == SEL_LEFT && allItemsAreSelected())
            {
                deselectAll();
                selectAtTick(song->cpos());
                return;
            }

            iCItem i, iLeftmost;
            CItem* leftmost = NULL;

            // get a list of items that belong to the current part
            // since multiple parts have populated the _items list
            // we need to filter on the actual current Part!
            CItemList list = _items;
            if(multiPartSelectionAction && !multiPartSelectionAction->isChecked())
                list = getItemlistForCurrentPart();

            if (list.size() > 0)
            {
                i = list.end();
                while (i != list.begin())
                {
                    --i;

                    if (i->second->isSelected())
                    {
                        iLeftmost = i;
                        leftmost = i->second;
                    }
                }
                if (leftmost)
                {
                    if (iLeftmost != list.begin())
                    {
                        //Add item
                        if (action != SEL_LEFT_ADD)
                            deselectAll();

                        iLeftmost--;
                        iLeftmost->second->setSelected(true);
                        itemPressed(iLeftmost->second);
                        m_tempPlayItems.append(iLeftmost->second);
                        QTimer::singleShot(NOTE_PLAY_TIME, this, SLOT(playReleaseForItem()));
                        if(editor->isGlobalEdit())
                            populateMultiSelect(iLeftmost->second);
                        updateSelection();
                    } else {
                        leftmost->setSelected(true);
                        itemPressed(leftmost);
                        m_tempPlayItems.append(leftmost);
                        QTimer::singleShot(NOTE_PLAY_TIME, this, SLOT(playReleaseForItem()));
                        if(editor->isGlobalEdit())
                            populateMultiSelect(leftmost);
                        updateSelection();
                    }
                } else // there was no item selected at all? Then select nearest to tick if there is any
                {
                    selectAtTick(song->cpos());
                    updateSelection();
                }
            }
        }
        break;
        case INC_PITCH_OCTAVE:
        {
            modifySelected(NoteInfo::VAL_PITCH, 12);
        }
        break;
        case DEC_PITCH_OCTAVE:
        {
            modifySelected(NoteInfo::VAL_PITCH, -12);
        }
        break;
        case INC_PITCH:
        {
            modifySelected(NoteInfo::VAL_PITCH, 1);
        }
        break;
        case DEC_PITCH:
        {
            modifySelected(NoteInfo::VAL_PITCH, -1);
        }
        break;
        case INC_POS:
        {
            // TODO: Check boundaries
            modifySelected(NoteInfo::VAL_TIME, editor->raster());
        }
        break;
        case DEC_POS:
        {
            // TODO: Check boundaries
            modifySelected(NoteInfo::VAL_TIME, 0 - editor->raster());
        }
        break;
        case INCREASE_LEN:
        {
            // TODO: Check boundaries
            modifySelected(NoteInfo::VAL_LEN, editor->raster());
        }
        break;
        case DECREASE_LEN:
        {
            // TODO: Check boundaries
            modifySelected(NoteInfo::VAL_LEN, 0 - editor->raster());
        }
        break;
        case GOTO_SEL_NOTE:
        {
            CItem* leftmost = getLeftMostSelected();
            if (leftmost)
            {
                unsigned newtick = leftmost->event().tick() + leftmost->part()->tick();
                Pos p1(newtick, true);
                song->setPos(0, p1, true, true, false);
            }
        }
        break;
        case MIDI_PANIC:
        {
            song->panic();
        }
        break;
    }
}/*}}}*/
Example #7
0
void EventCanvas::viewMousePressEvent(QMouseEvent* event)/*{{{*/
{
    ///keyState = event->state();
    _keyState = ((QInputEvent*) event)->modifiers();
    _button = event->button();

    //printf("viewMousePressEvent buttons:%x mods:%x button:%x\n", (int)event->buttons(), (int)keyState, event->button());

    // special events if right button is clicked while operations
    // like moving or drawing lasso is performed.
    if (event->buttons() & Qt::RightButton & ~(event->button()))
    {
        //printf("viewMousePressEvent special buttons:%x mods:%x button:%x\n", (int)event->buttons(), (int)keyState, event->button());
        switch (_drag)
        {
        case DRAG_LASSO:
            _drag = DRAG_OFF;
            redraw();
            return;
        case DRAG_MOVE:
            _drag = DRAG_OFF;
            endMoveItems(_start, MOVE_MOVE, 0);
            return;
        default:
            break;
        }
    }

    // ignore event if (another) button is already active:
    if (event->buttons() & (Qt::LeftButton | Qt::RightButton | Qt::MidButton) & ~(event->button()))
    {
        //printf("viewMousePressEvent ignoring buttons:%x mods:%x button:%x\n", (int)event->buttons(), (int)keyState, event->button());
        return;
    }
    bool shift = _keyState & Qt::ShiftModifier;
    bool alt = _keyState & Qt::AltModifier;
    bool ctrl = _keyState & Qt::ControlModifier;
    _start = event->pos();

    //---------------------------------------------------
    //    set curItem to item mouse is pointing
    //    (if any)
    //---------------------------------------------------

    CItemList list = _items;
    if(multiPartSelectionAction && !multiPartSelectionAction->isChecked())
        list = getItemlistForCurrentPart();
    if (virt())
    {
        _curItem = list.find(_start);//_items.find(_start);
    }
    else
    {
        _curItem = 0; //selectAtTick(_start.x());
        iCItem ius;
        bool usfound = false;
        for (iCItem i = list.begin(); i != list.end(); ++i)
        {
            MidiTrack* mtrack = (MidiTrack*)i->second->part()->track();
            int sy = _start.y();
            int p = y2pitch(sy);
            if(editor->isGlobalEdit())
                p += mtrack->getTransposition();
            int p2 = pitch2y(p);
            QPoint lpos(_start.x(), p2);
            QRect box = i->second->bbox();
            int x = rmapxDev(box.x());
            int y = rmapyDev(box.y());
            int w = rmapxDev(box.width());
            int h = rmapyDev(box.height());
            QRect r(x, y, w, h);
            r.translate(i->second->pos().x(), i->second->pos().y());
            if(r.contains(lpos))
            {
                if (i->second->isSelected())
                {
                    _curItem = i->second;
                    break;
                }
                else if (!usfound)
                {
                    ius = i;
                    usfound = true;
                }
            }
        }
        if (!_curItem && usfound)
            _curItem = ius->second;

    }

    if(editor->isGlobalEdit() && _curItem)
    {
        populateMultiSelect(_curItem);
    }

    if (_curItem && (event->button() == Qt::MidButton))
    {
        if (!_curItem->isSelected())
        {
            selectItem(_curItem, true);
            updateSelection();
            redraw();
        }
        startDrag(_curItem, shift);
    }
    else if (event->button() == Qt::RightButton)
    {
        if (_curItem)
        {
            if (shift)
            {
                _drag = DRAG_RESIZE;
                setCursor();
                int dx = _start.x() - _curItem->x();
                _curItem->setWidth(dx);
                _start.setX(_curItem->x());
                deselectAll();
                selectItem(_curItem, true);
                updateSelection();
                redraw();
            }
            else
            {
                _itemPopupMenu = genItemPopup(_curItem);
                if (_itemPopupMenu)
                {
                    QAction *act = _itemPopupMenu->exec(QCursor::pos());
                    if (act)
                        itemPopup(_curItem, act->data().toInt(), _start);
                    delete _itemPopupMenu;
                }
            }
        }
        else
        {
            _canvasPopupMenu = genCanvasPopup(true);
            if (_canvasPopupMenu)
            {
                QAction *act = _canvasPopupMenu->exec(QCursor::pos(), 0);
                if (act)
                {
                    int actnum = act->data().toInt();
                    canvasPopup(actnum);
                    if(actnum >= 20) //Nome of the tools have a higher number than 9
                    {
                        editor->updateCanvas();
                        los->arranger->updateCanvas();
                    }
                }
                delete _canvasPopupMenu;
            }
        }
    }
    else if (event->button() == Qt::LeftButton)
    {
        switch (_tool)
        {
        case PointerTool:
            if (_curItem)
            {
                /*if (_curItem->part() != _curPart)
                {
                    _curPart = _curItem->part();
                    _curPartId = _curPart->sn();
                    curPartChanged();
                }*/
                itemPressed(_curItem);
                if (shift)
                    _drag = DRAG_COPY_START;
                else if (alt)
                {
                    _drag = DRAG_CLONE_START;
                }
                else if (ctrl)
                { //Select all on the same pitch (e.g. same y-value)
                    deselectAll();
                    //printf("Yes, ctrl and press\n");
                    for (iCItem i = _items.begin(); i != _items.end(); ++i)
                    {
                        if (i->second->y() == _curItem->y())
                            selectItem(i->second, true);
                    }
                    updateSelection();
                    redraw();
                }
                else
                    _drag = DRAG_MOVE_START;
            }
            else
                _drag = DRAG_LASSO_START;
            setCursor();
            break;

            case RubberTool:
            deleteItem(_start);
            _drag = DRAG_DELETE;
            setCursor();
            break;

            case PencilTool:
            if (_curItem)
            {
                _drag = DRAG_RESIZE;
                setCursor();
                int dx = _start.x() - _curItem->x();
                _curItem->setWidth(dx);
                _start.setX(_curItem->x());
            }
            else
            {
                _drag = DRAG_NEW;
                setCursor();
                _curItem = newItem(_start, event->modifiers());
                if (_curItem)
                    _items.add(_curItem);
                else
                {
                    _drag = DRAG_OFF;
                    setCursor();
                }
            }
            deselectAll();
            if (_curItem)
            {
                selectItem(_curItem, true);
                // Play the note
                itemPressed(_curItem);
            }
            updateSelection();
            redraw();
            break;

            default:
            break;
        }
    }
    mousePress(event);
}/*}}}*/
Example #8
0
/*****************************************************************************
* CTTSEngObj::AddNextSentItem *
*-----------------------------*
*   Locates the next sentence item in the stream and adds it to the list.
*   Returns true if the last item added is the end of the sentence.
****************************************************************************/
BOOL CTTSEngObj::AddNextSentItem( CItemList& ItemList )
{
    //--- Get the token
    ULONG ulIndex;
    CSentItem Item;
    Item.pItem = FindNextToken( m_pNextChar, m_pEndChar, m_pNextChar );

    //--- This case can occur when we hit the end of a text fragment.
    //    Returning at this point will cause advancement to the next fragment.
    if( Item.pItem == NULL )
    {
        return false;
    }

    const WCHAR* pTrailChar = m_pNextChar-1;
    ULONG TokenLen = m_pNextChar - Item.pItem;

    //--- Split off leading punction if any
    static const WCHAR LeadItems[] = { L'(', L'\"', L'{', L'\'', L'[' };
    while( TokenLen > 1 )
    {
        if( SearchSet( Item.pItem[0], LeadItems, sp_countof(LeadItems), &ulIndex ) )
        {
            CSentItem LItem;
            LItem.pItem           = Item.pItem;
            LItem.ulItemLen       = 1;
            LItem.pXmlState       = &m_pCurrFrag->State;
            LItem.ulItemSrcLen    = LItem.ulItemLen;
            LItem.ulItemSrcOffset = m_pCurrFrag->ulTextSrcOffset +
                                    ( LItem.pItem - m_pCurrFrag->pTextStart );
            ItemList.AddTail( LItem );
            ++Item.pItem;
            --TokenLen;
        }
        else
        {
            break;
        }
    }

    //--- Get primary item insert position
    SPLISTPOS ItemPos = ItemList.AddTail( Item );

    //--- Split off trailing punction if any.
    static const WCHAR EOSItems[] = { L'.', L'!', L'?' };
    static const WCHAR TrailItems[] = { L',', L'\"', L';', L':', L')', L'}', L'\'', L']' };
    SPLISTPOS NextPos = NULL;
    BOOL fIsEOS = false;
    while( TokenLen > 1 )
    {
        BOOL fAddTrailItem = false;
        if( SearchSet( *pTrailChar, EOSItems, sp_countof(EOSItems), &ulIndex ) )
        {
            fIsEOS = true;
            fAddTrailItem = true;
        }
        else if( SearchSet( *pTrailChar, TrailItems, sp_countof(TrailItems), &ulIndex ) )
        {
            fAddTrailItem = true;
        }

        if( fAddTrailItem )
        {
            CSentItem TItem;
            TItem.pItem           = pTrailChar;
            TItem.ulItemLen       = 1;
            TItem.pXmlState       = &m_pCurrFrag->State;
            TItem.ulItemSrcLen    = TItem.ulItemLen;
            TItem.ulItemSrcOffset = m_pCurrFrag->ulTextSrcOffset +
                                    ( TItem.pItem - m_pCurrFrag->pTextStart );
            NextPos = ItemList.InsertAfter( ItemPos, TItem );
            --TokenLen;
            --pTrailChar;
        }
        else
        {
            break;
        }
    }

    //--- Abreviation or sentence end?
    //    If we are at the end of the buffer then EOS is implied.
    if( *m_pNextChar == NULL )
    {
        fIsEOS = true;
        if( !SearchSet( *(m_pNextChar-1), EOSItems, sp_countof(EOSItems), &ulIndex ) )
        {
            //--- Terminate with a period if we are at the end of a buffer
            //    and no end of sentence punction has been added.
            static const WCHAR* pPeriod = L".";
            CSentItem EOSItem;
            EOSItem.pItem           = pPeriod;
            EOSItem.ulItemLen       = 1;
            EOSItem.pXmlState       = &m_pCurrFrag->State;
            EOSItem.ulItemSrcLen    = EOSItem.ulItemLen;
            EOSItem.ulItemSrcOffset = m_pCurrFrag->ulTextSrcOffset +
                                    ( (m_pNextChar-1) - m_pCurrFrag->pTextStart );
            ItemList.AddTail( EOSItem );
        }
    }
    else if( pTrailChar[1] == L'.' )
    {
        //--- Here is where you would try to prove that it's not EOS
        //    It might be an abreviation. That's a hard problem that
        //    we are not going to attempt here.
    }
    
    //--- Substitute underscore for apostrophe
    for( ULONG i = 0; i < TokenLen; ++i )
    {
        if( Item.pItem[i] == L'\'' )
        {
            ((WCHAR)Item.pItem[i]) = L'_';
        }
    }

    //--- Add the main item
    if( TokenLen > 0 )
    {
        Item.ulItemLen       = TokenLen;
        Item.pXmlState       = &m_pCurrFrag->State;
        Item.ulItemSrcLen    = Item.ulItemLen;
        Item.ulItemSrcOffset = m_pCurrFrag->ulTextSrcOffset +
                               ( Item.pItem - m_pCurrFrag->pTextStart );
        ItemList.SetAt( ItemPos, Item );
    }

    return fIsEOS;
} /* CTTSEngObj::AddNextSentItem */
Example #9
0
/*****************************************************************************
* CTTSEngObj::GetNextSentence *
*-----------------------------*
*   This method is used to create a list of items to be spoken.
****************************************************************************/
HRESULT CTTSEngObj::GetNextSentence( CItemList& ItemList )
{
    HRESULT hr = S_OK;

    //--- Clear the destination
    ItemList.RemoveAll();

    //--- Is there any work to do
    if( m_pCurrFrag == NULL )
    {
        hr = S_FALSE;
    }
    else
    {
        BOOL fSentDone = false;
        BOOL fGoToNextFrag = false;

        while( m_pCurrFrag && !fSentDone )
        {
            if( m_pCurrFrag->State.eAction == SPVA_Speak )
            {
                fSentDone = AddNextSentItem( ItemList );

                //--- Advance fragment?
                if( m_pNextChar >= m_pEndChar )
                {
                    fGoToNextFrag = true;
                }
            }
            else
            {
                //--- Add non spoken fragments
                CSentItem Item;
                Item.pItem           = m_pCurrFrag->pTextStart;
                Item.ulItemLen       = m_pCurrFrag->ulTextLen;
                Item.ulItemSrcOffset = m_pCurrFrag->ulTextSrcOffset;
                Item.ulItemSrcLen    = Item.ulItemLen;
                Item.pXmlState       = &m_pCurrFrag->State;
                ItemList.AddTail( Item );
                fGoToNextFrag = true;
            }

            if( fGoToNextFrag )
            {
                fGoToNextFrag = false;
                m_pCurrFrag = m_pCurrFrag->pNext;
                if( m_pCurrFrag )
                {
                    m_pNextChar = m_pCurrFrag->pTextStart;
                    m_pEndChar  = m_pNextChar + m_pCurrFrag->ulTextLen;
                }
                else
                {
                    m_pNextChar = NULL;
                    m_pEndChar  = NULL;
                }
            }
        } // end while

        if( ItemList.IsEmpty() )
        {
            hr = S_FALSE;
        }
    }
    return hr;
} /* CTTSEngObj::GetNextSentence */
Example #10
0
/*****************************************************************************
* CTTSEngObj::OutputSentence *
*----------------------------*
*   This method is used to output an item list.
****************************************************************************/
HRESULT CTTSEngObj::OutputSentence( CItemList& ItemList, ISpTTSEngineSite* pOutputSite )
{
    HRESULT hr = S_OK;
    ULONG WordIndex;

    //--- Lookup words in our voice
    SPLISTPOS ListPos = ItemList.GetHeadPosition();
    while( ListPos && !(pOutputSite->GetActions() & SPVES_ABORT) )
    {
        CSentItem& Item = ItemList.GetNext( ListPos );

        //--- Process sentence items
        switch( Item.pXmlState->eAction )
        {
          //--- Speak some text ---------------------------------------
          case SPVA_Speak:
          {
            //--- We don't say anything for punctuation or control characters
            //    in this sample. 
            if( iswalpha( Item.pItem[0] ) || iswdigit( Item.pItem[0] ) )
            {
                //--- Lookup the word, if we can't find it just use the first one
                for( WordIndex = 0; WordIndex < m_ulNumWords; ++WordIndex )
                {
                    if( ( m_pWordList[WordIndex].ulTextLen == Item.ulItemLen ) &&
                        ( !wcsnicmp( m_pWordList[WordIndex].pText, Item.pItem, Item.ulItemLen )) )
                    {
                        break;
                    }
                }
                if( WordIndex == m_ulNumWords )
                {
                    WordIndex = 0;
                }

                //--- Queue the event
                CSpEvent Event;
                Event.eEventId             = SPEI_WORD_BOUNDARY;
                Event.elParamType          = SPET_LPARAM_IS_UNDEFINED;
                Event.ullAudioStreamOffset = m_ullAudioOff;
                Event.lParam               = Item.ulItemSrcOffset;
                Event.wParam               = Item.ulItemSrcLen;
                hr = pOutputSite->AddEvents( &Event, 1 );

                //--- Queue the audio data
                hr = pOutputSite->Write( m_pWordList[WordIndex].pAudio,
                                         m_pWordList[WordIndex].ulNumAudioBytes,
                                         NULL );

                //--- Update the audio offset
                m_ullAudioOff += m_pWordList[WordIndex].ulNumAudioBytes;
            }
          }
          break;

          //--- Output some silence for a pause -----------------------
          case SPVA_Silence:
          {
            BYTE Buff[1000];
            memset( Buff, 0, 1000 );
            ULONG NumSilenceBytes = Item.pXmlState->SilenceMSecs * 22;

            //--- Queue the audio data in chunks so that we can get
            //    interrupted if necessary.
            while( !(pOutputSite->GetActions() & SPVES_ABORT) )
            {
                if( NumSilenceBytes > 1000 )
                {
                    hr = pOutputSite->Write( Buff, 1000, NULL );
                    NumSilenceBytes -= 1000;
                }
                else
                {
                    hr = pOutputSite->Write( Buff, NumSilenceBytes, NULL );
                    break;
                }
            }

            //--- Update the audio offset
            m_ullAudioOff += NumSilenceBytes;
          }
          break;

          //--- Fire a bookmark event ---------------------------------
          case SPVA_Bookmark:
          {
            //--- The bookmark is NOT a null terminated string in the Item, but we need
            //--- to convert it to one.  Allocate enough space for the string.
            WCHAR * pszBookmark = (WCHAR *)_alloca((Item.ulItemLen + 1) * sizeof(WCHAR));
            memcpy(pszBookmark, Item.pItem, Item.ulItemLen * sizeof(WCHAR));
            pszBookmark[Item.ulItemLen] = 0;
            //--- Queue the event
            SPEVENT Event;
            Event.eEventId             = SPEI_TTS_BOOKMARK;
            Event.elParamType          = SPET_LPARAM_IS_STRING;
            Event.ullAudioStreamOffset = m_ullAudioOff;
            Event.lParam               = (LPARAM)pszBookmark;
            Event.wParam               = _wtol(pszBookmark);
            hr = pOutputSite->AddEvents( &Event, 1 );
          }
          break;

          case SPVA_Pronounce:
            //--- Our sample engine doesn't handle this. If it
            //    did, you would use the associated pronunciation in
            //    the XmlState structure instead of the lexicon.
            break;

          case SPVA_ParseUnknownTag:
            //--- This will reference an XML tag that is unknown to SAPI
            //    if your engine has private tags to control state, you
            //    would examine these tags and see if you recognize it. This
            //    would also be the point that you would make the rendering
            //    state change.
            break;
        }
    }

    return hr;
} /* CTTSEngObj::OutputSentence */
Example #11
0
/*****************************************************************************
* CTTSEngObj::Speak *
*-------------------*
*   Description:
*       This is the primary method that SAPI calls to render text.
*-----------------------------------------------------------------------------
*   Input Parameters
*
*   pUser
*       Pointer to the current user profile object. This object contains
*       information like what languages are being used and this object
*       also gives access to resources like the SAPI master lexicon object.
*
*   dwSpeakFlags
*       This is a set of flags used to control the behavior of the
*       SAPI voice object and the associated engine.
*
*   VoiceFmtIndex
*       Zero based index specifying the output format that should
*       be used during rendering.
*
*   pTextFragList
*       A linked list of text fragments to be rendered. There is
*       one fragement per XML state change. If the input text does
*       not contain any XML markup, there will only be a single fragment.
*
*   pOutputSite
*       The interface back to SAPI where all output audio samples and events are written.
*
*   Return Values
*       S_OK - This should be returned after successful rendering or if
*              rendering was interrupted because *pfContinue changed to FALSE.
*       E_INVALIDARG 
*       E_OUTOFMEMORY
*
*****************************************************************************/
STDMETHODIMP CTTSEngObj::Speak( DWORD dwSpeakFlags,
                                REFGUID rguidFormatId,
                                const WAVEFORMATEX * pWaveFormatEx,
                                const SPVTEXTFRAG* pTextFragList,
                                ISpTTSEngineSite* pOutputSite )
{
    SPDBG_FUNC( "CTTSEngObj::Speak" );
    HRESULT hr = S_OK;

    //--- Check args
    if( SP_IS_BAD_INTERFACE_PTR( pOutputSite ) ||
        SP_IS_BAD_READ_PTR( pTextFragList )  )
    {
        hr = E_INVALIDARG;
    }
    else
    {
        //--- Init some vars
        m_pCurrFrag   = pTextFragList;
        m_pNextChar   = m_pCurrFrag->pTextStart;
        m_pEndChar    = m_pNextChar + m_pCurrFrag->ulTextLen;
        m_ullAudioOff = 0;

        //--- Parse
        //    We've supplied a simple word/sentence breaker just to show one
        //    way of walking the fragment list. It obviously doesn't deal with
        //    things like abreviations and expansion of numbers and dates.
        CItemList ItemList;

        while( SUCCEEDED( hr ) && !(pOutputSite->GetActions() & SPVES_ABORT) )
        {
            //--- Do skip?
            if( pOutputSite->GetActions() & SPVES_SKIP )
            {
                long lSkipCnt;
                SPVSKIPTYPE eType;
                hr = pOutputSite->GetSkipInfo( &eType, &lSkipCnt );
                if( SUCCEEDED( hr ) )
                {
                    //--- Notify SAPI how many items we skipped. We're returning zero
                    //    because this feature isn't implemented.
                    hr = pOutputSite->CompleteSkip( 0 );
                }
            }

            //--- Build the text item list
            if( SUCCEEDED( hr ) && (hr = GetNextSentence( ItemList )) != S_OK )
            {
                break;                
            }

            //--- We aren't going to do any part of speech determination,
            //    prosody, or pronunciation determination. If you were, one thing
            //    you will need is access to the SAPI lexicon. You can get that with
            //    the following call.
            //    CComPtr<ISpLexicon> cpLexicon;
            //    hr = pUser->GetLexicon( &cpLexicon );

            if( !(pOutputSite->GetActions() & SPVES_ABORT) )
            {
                //--- Fire begin sentence event
                CSentItem& FirstItem = ItemList.GetHead();
                CSentItem& LastItem  = ItemList.GetTail();
                CSpEvent Event;
                Event.eEventId             = SPEI_SENTENCE_BOUNDARY;
                Event.elParamType          = SPET_LPARAM_IS_UNDEFINED;
                Event.ullAudioStreamOffset = m_ullAudioOff;
                Event.lParam               = (LPARAM)FirstItem.ulItemSrcOffset;
                Event.wParam               = (WPARAM)LastItem.ulItemSrcOffset +
                                                     LastItem.ulItemSrcLen -
                                                     FirstItem.ulItemSrcOffset;
                hr = pOutputSite->AddEvents( &Event, 1 );

                //--- Output
                if( SUCCEEDED( hr ) )
                {
                    hr = OutputSentence( ItemList, pOutputSite );
                }
            }
        }

        //--- S_FALSE just says that we hit the end, return okay
        if( hr == S_FALSE )
        {
            hr = S_OK;
        }
    }

    return hr;
} /* CTTSEngObj::Speak */
Example #12
0
void AbstractMidiEditor::songChanged(int type)/*{{{*/
{
    if (type)
    {
        if (type & (SC_PART_REMOVED | SC_PART_MODIFIED
                | SC_PART_INSERTED | SC_TRACK_REMOVED))
        {
            genPartlist();
            // close window if editor has no parts anymore
            if (parts()->empty())
            {
                close();
                return;
            }
        }
        if (canvas)
            canvas->songChanged(type);

        if (type & (SC_PART_REMOVED | SC_PART_MODIFIED
                | SC_PART_INSERTED | SC_TRACK_REMOVED))
        {

            updateHScrollRange();
            if (canvas)
                setWindowTitle(canvas->getCaption());
            if (type & SC_SIG)
                time->update();

        }

        if (type & SC_SELECTION)
        {
                CItemList list = canvas->getSelectedItemsForCurrentPart();

                //Get the rightmost selected note (if any)
                iCItem i, iRightmost;
                CItem* rightmost = NULL;

                i = list.begin();
                while (i != list.end())
                {
                        if (i->second->isSelected())
                        {
                                iRightmost = i;
                                rightmost = i->second;
                        }

                        ++i;
                }

                if (rightmost)
                {
                        int pos = rightmost->pos().x();
                        pos = canvas->mapx(pos) + hscroll->offset();
                        int s = hscroll->offset();
                        int e = s + canvas->width();

                        if (pos > e)
                                hscroll->setOffset(rightmost->pos().x());
                        if (pos < s)
                                hscroll->setOffset(rightmost->pos().x());
                }
        }

    }
}/*}}}*/
Example #13
0
void CGroupOfGenerators::AddItems (SItemAddCtx &Ctx)

//	AddItems
//
//	Add items

	{
	int i, j;

	//	If we need to adjust counts, then do a separate algorithm

	if (SetsAverageValue())
		{
		//	Get the count adjustment.

		Metric rCountAdj = GetCountAdj(Ctx.iLevel);
		Metric rLoops = floor(rCountAdj);
		Metric rLastLoopAdj = rCountAdj - rLoops;

		//	Loop if we have extra items

		int iFullLoops = (int)rLoops;
		for (i = 0; i < iFullLoops + 1; i++)
			{
			//	For a full loop we just add the items

			if (i < iFullLoops)
				AddItemsInt(Ctx);

			//	Otherwise we need to add partial items

			else
				{
				//	Add the items to a private list.

				CItemList LocalList;
				CItemListManipulator ItemList(LocalList);
				SItemAddCtx LocalCtx(ItemList);
				LocalCtx.iLevel = Ctx.iLevel;
				AddItemsInt(LocalCtx);

				//	Now loop over the items and adjust the count appropriately.

				for (j = 0; j < LocalList.GetCount(); j++)
					{
					const CItem &Item = LocalList.GetItem(j);
					int iOriginalCount = Item.GetCount();

					//	Adjust the count

					Metric rNewCount = iOriginalCount * rLastLoopAdj;
					Metric rNewCountInt = floor(rNewCount);
					int iNewCount = (int)rNewCountInt;

					Metric rExtra = rNewCount - rNewCountInt;
					int iExtraChance = (int)(100000.0 * rExtra);
					if (mathRandom(0, 100000) < iExtraChance)
						iNewCount++;

					//	Add the item with the new count

					if (iNewCount > 0)
						{
						if (iNewCount == iOriginalCount)
							Ctx.ItemList.AddItem(Item);
						else
							{
							CItem NewItem(Item);
							NewItem.SetCount(iNewCount);
							Ctx.ItemList.AddItem(NewItem);
							}
						}
					}
				}
			}
		}
	else
		AddItemsInt(Ctx);
	}